最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?Security如何為用戶示例添加角色詳解

 更新時間:2022年10月08日 09:05:42   作者:allway2  
目前我正在用Java開發(fā)一個基于Spring Boot的web應(yīng)用程序,下面這篇文章主要給大家介紹了關(guān)于Spring?Security如何為用戶示例添加角色的相關(guān)資料,需要的朋友可以參考下

前言

在這個 Spring Security 教程中,我很樂意與您分享如何通過在 Java Web 應(yīng)用程序中為用戶添加角色來實現(xiàn)授權(quán)——從數(shù)據(jù)庫設(shè)計到實體類;從單元測試到在用戶注冊中添加默認(rèn)角色;以 Web 形式更新用戶的角色。

技術(shù):Spring Web MVC、Spring Data JPA、Hibernate 框架、Spring Security、Spring Boot Test、JUnit 5、AssertJ、Thymeleaf 和 MySQL 數(shù)據(jù)庫。

基本上,我們需要在數(shù)據(jù)庫中有 3 個表,如下所示:

一個用戶可以有一個或多個角色,一個角色可以分配給一個或多個用戶,因此用戶和角色表之間的實體關(guān)系是多對多的。users_roles是實現(xiàn)這種關(guān)系的中間表。

1. 用戶和角色實體類和存儲庫的代碼

將User 實體類編碼如下:

package net.codejava;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.*;
 
@Entity
@Table(name = "users")
public class User {
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	@Column(nullable = false, unique = true, length = 45)
	private String email;
	
	@Column(nullable = false, length = 64)
	private String password;
	
	@Column(name = "first_name", nullable = false, length = 20)
	private String firstName;
	
	@Column(name = "last_name", nullable = false, length = 20)
	private String lastName;
	
	@ManyToMany(fetch = FetchType.EAGER)
	@JoinTable(
			name = "users_roles",
			joinColumns = @JoinColumn(name = "user_id"),
			inverseJoinColumns = @JoinColumn(name = "role_id")
	)
	private Set<Role> roles = new HashSet<>();
 
	public void addRole(Role role) {
		this.roles.add(role);
}
 
	// getters and setters are not shown for brevity
}

并像這樣對Role 實體類進(jìn)行編碼:

package net.codejava;
 
import javax.persistence.*;
 
@Entity
@Table(name = "roles")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
     
    @Column(nullable = false, length = 45)
    private String name;
 
    public Role() { }
     
    public Role(String name) {
        this.name = name;
    }
     
    public Role(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
 
    public Role(Integer id) {
        this.id = id;
    }
     
 
    @Override
    public String toString() {
        return this.name;
    }
 
    // getters and setters are not shown for brevity   
}

如您所見,User類有一組角色,但Role類沒有任何對 User 的引用。默認(rèn)情況下, @ManyToMany關(guān)系上沒有級聯(lián)操作——這意味著更新User對象不會更改關(guān)聯(lián)的Role對象。

2. 單元測試——創(chuàng)建角色  

接下來,讓我們編寫以下測試類,用于將一些Role對象持久化到數(shù)據(jù)庫中:

package net.codejava;
 
import static org.assertj.core.api.Assertions.assertThat;
 
import java.util.List;
 
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.annotation.Rollback;
 
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
@Rollback(false)
public class RoleRepositoryTests {
 
    @Autowired private RoleRepository repo;
     
    @Test
    public void testCreateRoles() {
        Role user = new Role("User");
        Role admin = new Role("Admin");
        Role customer = new Role("Customer");
         
        repo.saveAll(List.of(user, admin, customer));
         
        List<Role> listRoles = repo.findAll();
         
        assertThat(listRoles.size()).isEqualTo(3);
    }
     
}

運行testCreateRoles()方法,我們最終將根據(jù) 3 個角色將 3 個新行插入到角色表中:用戶、管理員和客戶。

3. 單元測試——給用戶添加角色

要測試向用戶添加角色,請使用以下初始代碼創(chuàng)建UserRepositoryTests類:

package net.codejava;
 
import static org.assertj.core.api.Assertions.assertThat;
 
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.annotation.Rollback;
 
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
@Rollback(false)
public class UserRepositoryTests {
 
    @Autowired
    private TestEntityManager entityManager;
     
    @Autowired
    private UserRepository userRepo;
     
    @Autowired
    private RoleRepository roleRepo;
     
    // test methods go here...
}

以下是第一個測試方法的代碼片段,它保留了一個沒有任何角色的用戶對象:

@Test
public void testCreateUser() {
    User user = new User();
    user.setEmail("ravikumar@gmail.com");
    user.setPassword("ravi2020");
    user.setFirstName("Ravi");
    user.setLastName("Kumar");
     
    User savedUser = userRepo.save(user);
     
    User existUser = entityManager.find(User.class, savedUser.getId());
     
    assertThat(user.getEmail()).isEqualTo(existUser.getEmail());
     
}

以下測試方法創(chuàng)建一個具有管理員角色的新用戶:

@Test
public void testAddRoleToNewUser() {
    Role roleAdmin = roleRepo.findByName("Admin");
     
    User user = new User();
    user.setEmail("mikes.gates@gmail.com");
    user.setPassword("mike2020");
    user.setFirstName("Mike");
    user.setLastName("Gates");
    user.addRole(roleAdmin);       
     
    User savedUser = userRepo.save(user);
     
    assertThat(savedUser.getRoles().size()).isEqualTo(1);
}

以下測試將通過添加兩個角色 User 和 Customer 來更新現(xiàn)有用戶:

@Test
public void testAddRoleToExistingUser() {
    User user = userRepo.findById(1L).get();
    Role roleUser = roleRepo.findByName("User");
    Role roleCustomer = new Role(3);
     
    user.addRole(roleUser);
    user.addRole(roleCustomer);
     
    User savedUser = userRepo.save(user);
     
    assertThat(savedUser.getRoles().size()).isEqualTo(2);      
}

運行這些測試方法,您將看到插入到users和users_roles表中的行。角色表不受影響。

4. 為注冊用戶設(shè)置默認(rèn)角色

用戶注冊中的一個常見場景是為新注冊的用戶設(shè)置默認(rèn)角色,例如用戶或客戶角色。以下是服務(wù)層的示例代碼片段:

package net.codejava;
 
@Service
public class UserService {
 
    @Autowired
    private UserRepository userRepo;
     
    @Autowired RoleRepository roleRepo;
     
    @Autowired PasswordEncoder passwordEncoder;
     
    public void registerDefaultUser(User user) {
        Role roleUser = roleRepo.findByName("User");
        user.addRole(roleUser);
 
        userRepo.save(user);
    }
     
}

以及控制器層的代碼:

package net.codejava;
 
@Controller
public class AppController {
 
    @Autowired
    private UserService service;
         
    @PostMapping("/register")
    public String processRegister(User user) {
        service.registerDefaultUser(user);
         
        return "register_success";
    }  
}

如您所見,這非常簡單——感謝 Spring Data JPA 和 Hibernate 框架,極大地簡化了數(shù)據(jù)訪問層的編碼。

5. 在 Web 表單中為用戶分配角色

現(xiàn)在,我將向您展示如何使用 Web 用戶界面編寫編輯用戶功能的代碼,我們可以在其中更改分配給用戶的角色。

首先,在UserService 類中實現(xiàn)如下方法:

public List<User> listAll() {
    return userRepo.findAll();
}

在控制器類中:

@GetMapping("/users")
public String listUsers(Model model) {
    List<User> listUsers = service.listAll();
    model.addAttribute("listUsers", listUsers);
     
    return "users";
}

此處理程序方法將顯示從數(shù)據(jù)庫中檢索到的用戶列表。并將以下相關(guān)代碼放入視圖頁面(HTML):

<table class="table table-striped table-bordered">
    <thead class="thead-dark">
        <tr>
            <th>User ID</th>
            <th>E-mail</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Roles</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr th:each="user: ${listUsers}">
            <td th:text="${user.id}">User ID</td>
            <td th:text="${user.email}">E-mail</td>
            <td th:text="${user.firstName}">First Name</td>
            <td th:text="${user.lastName}">Last Name</td>
            <td th:text="${user.roles}">Roles</td>
            <td><a th:href="/@{'/users/edit/' + ${user.id}}">Edit</a></td>
        </tr>
    </tbody>
</table>

它將在 URL http://localhost.../users 處顯示用戶列表,如下所示:

在此用戶列表頁面上,我們可以單擊編輯超鏈接來編輯用戶。所以像這樣編寫處理程序方法:

@GetMapping("/users/edit/{id}")
public String editUser(@PathVariable("id") Long id, Model model) {
    User user = service.get(id);
    List<Role> listRoles = service.listRoles();
    model.addAttribute("user", user);
    model.addAttribute("listRoles", listRoles);
    return "user_form";
}

并在服務(wù)類中實現(xiàn)以下兩個方法:

public User get(Long id) {
    return userRepo.findById(id).get();
}
 
public List<Role> listRoles() {
    return roleRepo.findAll();
}

在視圖層,為編輯用戶表單編寫如下代碼:

<form th:action="@{/users/save}" th:object="${user}"
    method="post" style="max-width: 600px; margin: 0 auto;">
    <input type="hidden" th:field="*{id}" />
<div class="m-3">
    <div class="form-group row">
        <label class="col-4 col-form-label">E-mail: </label>
        <div class="col-8">
            <input type="email" th:field="*{email}" class="form-control" required />
        </div>
    </div>
     
    <div class="form-group row">
        <label class="col-4 col-form-label">Password: </label>
        <div class="col-8">
            <input type="password" th:field="*{password}" class="form-control"
                    required minlength="6" maxlength="10"/>
        </div>
    </div>
     
    <div class="form-group row">
        <label class="col-4 col-form-label">First Name: </label>
        <div class="col-8">
            <input type="text" th:field="*{firstName}" class="form-control"
                    required minlength="2" maxlength="20"/>
        </div>
    </div>
     
    <div class="form-group row">
        <label class="col-4 col-form-label">Last Name: </label>
        <div class="col-8">
            <input type="text" th:field="*{lastName}" class="form-control"
                    required minlength="2" maxlength="20" />
        </div>
    </div>
     
    <div class="form-group row">
        <label class="col-4 col-form-label">Roles: </label>
        <div class="col-8">
            <th:block th:each="role: ${listRoles}">
            <input type="checkbox" th:field="*{roles}"
                th:text="${role.name}" th:value="${role.id}" class="m-2" />
            </th:block>
        </div>
    </div>           
     
    <div>
        <button type="submit" class="btn btn-primary">Update</button>
    </div>
</div>
</form>

此頁面中最重要的是顯示角色列表并檢查分配給當(dāng)前用戶的角色的代碼:

<th:block th:each="role: ${listRoles}">
<input type="checkbox" th:field="*{roles}"
    th:text="${role.name}" th:value="${role.id}" class="m-2" />
</th:block>

然后編輯用戶表單將如下所示:

這里很酷的是,Thymeleaf 會根據(jù)分配給用戶的角色自動顯示選擇的角色。此外,您可以在此處簡單地選中/取消選中角色來更新用戶的角色。

并編寫處理表單提交的處理程序方法,如下所示:

@PostMapping("/users/save")
public String saveUser(User user) {
    service.save(user);
     
    return "redirect:/users";
}

以及服務(wù)層的相關(guān)代碼:

public void save(User user) {
    userRepo.save(user);
}

這是一些關(guān)于在 Spring Boot Web 應(yīng)用程序中向用戶添加角色的代碼示例。我希望您發(fā)現(xiàn)這個書面教程對您有所幫助。

總結(jié)

到此這篇關(guān)于Spring Security如何為用戶示例添加角色的文章就介紹到這了,更多相關(guān)Spring Security用戶示例添加角色內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中字符串拼接的一些細(xì)節(jié)分析

    Java中字符串拼接的一些細(xì)節(jié)分析

    這篇文章主要介紹了Java中字符串拼接的一些細(xì)節(jié)分析,本文著重剖析了字符串拼接的一些性能問題、技巧等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • 一文詳解Java如何實現(xiàn)自定義注解

    一文詳解Java如何實現(xiàn)自定義注解

    Java實現(xiàn)自定義注解其實很簡單,跟類定義差不多,只是屬性的定義可能跟我們平時定義的屬性略有不同,這篇文章主要給大家介紹了關(guān)于Java如何實現(xiàn)自定義注解的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • java多線程CountDownLatch與線程池ThreadPoolExecutor/ExecutorService案例

    java多線程CountDownLatch與線程池ThreadPoolExecutor/ExecutorService案

    這篇文章主要介紹了java多線程CountDownLatch與線程池ThreadPoolExecutor/ExecutorService案例,
    2021-02-02
  • Java字節(jié)緩存流的構(gòu)造方法之文件IO流

    Java字節(jié)緩存流的構(gòu)造方法之文件IO流

    這篇文章主要介紹了Java字節(jié)緩存流的構(gòu)造方法之文件IO流,同時也介紹了字符流中的一些相關(guān)的內(nèi)容,并且通過大量的案例供大家理解。最后通過一些經(jīng)典的案例幫助大家對前面所學(xué)的知識做了一個綜合的應(yīng)用,需要的朋友可以參考一下
    2022-04-04
  • maven打包插件的使用(maven-compiler-plugin、maven-dependency-plugin、maven-jar-plugin、maven-resources-plugin)

    maven打包插件的使用(maven-compiler-plugin、maven-dependency-plugin、m

    本文主要介紹了maven打包插件的使用(maven-compiler-plugin、maven-dependency-plugin、maven-jar-plugin、maven-resources-plugin),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 根據(jù)list中對象的屬性去重和排序小結(jié)(必看篇)

    根據(jù)list中對象的屬性去重和排序小結(jié)(必看篇)

    下面小編就為大家?guī)硪黄鶕?jù)list中對象的屬性去重和排序小結(jié)(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 存儲過程創(chuàng)建及springboot代碼調(diào)用存儲過程方式

    存儲過程創(chuàng)建及springboot代碼調(diào)用存儲過程方式

    文章介紹了如何在Navicat中創(chuàng)建存儲過程,并在Spring Boot項目中調(diào)用存儲過程,存儲過程創(chuàng)建步驟包括選擇函數(shù)類型、自定義函數(shù)名、添加參數(shù)等,在Spring Boot中調(diào)用存儲過程時,可以通過JdbcTemplate或MyBatis等工具進(jìn)行
    2024-11-11
  • Spring MVC訪問靜態(tài)文件_動力節(jié)點Java學(xué)院整理

    Spring MVC訪問靜態(tài)文件_動力節(jié)點Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了Spring MVC訪問靜態(tài)文件的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Spring Boot整合elasticsearch的詳細(xì)步驟

    Spring Boot整合elasticsearch的詳細(xì)步驟

    這篇文章主要介紹了Spring Boot整合elasticsearch的詳細(xì)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 代碼詳解java里的“==”和“equels”區(qū)別

    代碼詳解java里的“==”和“equels”區(qū)別

    本篇文章通過實例代碼給大家詳細(xì)解釋了java里的“==”和“equels”區(qū)別,對此有興趣的朋友跟著小編一起學(xué)習(xí)下。
    2018-02-02

最新評論

六安市| 甘洛县| 石屏县| 惠州市| 申扎县| 临洮县| 达州市| 宾川县| 宝丰县| 肃南| 尉氏县| 沅陵县| 福建省| 固镇县| 郑州市| 德昌县| 郑州市| 牙克石市| 焦作市| 屯门区| 西安市| 无锡市| 维西| 通榆县| 澄江县| 当雄县| 板桥市| 静乐县| 沈丘县| 肥乡县| 贵定县| 湖南省| 开鲁县| 中宁县| 宝鸡市| 洮南市| 九台市| 景谷| 西青区| 荥经县| 江华|