SpringBoot实现不同用户不同访问权限的示例代码
目录
- 前提
- 实现
- 1. 添加必要依赖
- 2. 数据库表设计
- 3. 实体类设计
- 4. 创建 Repository 接口
- 5. 实现 UserDetailsService
- 6. 配置 Spring Security
- 7. 创建控制器
- 8. 测试用户数据
- 权限控制说明
前提
近期在使用 Spring Boot,用户角色被分为管理者和普通用户;角色不同,权限也就存在不同。
在 Spring Boot 里实现不同用户拥有不同访问权限,可借助 Spring Security 框架达成。
实现
1. 添加必要依赖
首先要在 pom.XML
里添加 Spring Secur编程ity 和 JPA 的依赖。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-Java</artifactId> <scope>runtime</scope> </dependency> </dependencies>
2. 数据库表设计
创建三张表,分别是用户表、角色表以及用户角色关联表:
CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, enabled BOOLEAN DEFAULT true ); CREATE TABLE roles ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL UNIQUE ); CREATE TABLE user_roles ( user_id INT NOT NULL, role_id INT NOT NULL, PRIMARY KEY (user_id, role_id), FOREIGN KEY (user_id) REFERENCES users(id), FOREIGN KEY (role_id) REFERENCES roles(id) );
3. 实体类设计
创建与数据库表对应的实体类:
// User.java import javax.persistence.*; import java.util.Set; @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; private boolean enabled; @ManyToMany(fetch = FetchType.EAGER) @JoinTable( name = "user_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id") ) private Set<Role> roles; // getters and setters } // Role.java import javax.persistence.*; @Entity @Table(name = "roles") public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // getters and setters }
4. 创建 Repository 接口
为 User 和 Role 分别创建 Repository 接口,用于数据访问:
// UserRepository.java import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepository extends JpaRepository<User, Long> { User findByUsername(String username); } // RoleRepository.java import org.springframework.data.jpa.repository.JpaRepository; public interface RoleRepository extends JpaRepository<Role, Long> { Role findByName(String name); }
5. 实现 UserDetailsService
实现 Spring Security 的 UserDetailsService 接口,从数据库加载用户信息:
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.编程客栈util.Set; @Service public class CustomUserDetailsService implements UserDetailsService { private final UserRepository userRepository; public CustomUserDetailsService(UserRepository userRepository) { this.userRepository = userRepository; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found with username: " + username); } return new org.springframework.security.core.userdetails.User( user.getUsername(), user.getPassword(), user.isEnabled(), true, true, true, getAuthorities(user.getRoles()) ); } private List<GrantedAuthority> getAuthorities(Set<Role> roles) { List<GrantedAuthority> authorities = new ArrayList<>(); for (Role role : roles) { authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName())); } return authorities; } }
6. 配置 Spring Security
对 Spring Security 进行配置,设置不同 URL 的访问权限:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; @Configjsuration @EnableWebSecurity public class SecurityConfig { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/public/**").permitAll() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/user/**").hasAnyRole("USER", "ADMIN") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); return http.build(); } }
7. 创建控制器
创建不同权限的控制器示例:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/public/hello") public String publicHello() { return "Public Hello!"; } @GetMapping("/upythonser/hello") public String userHello() { return "User Hello!"; } @GetMapping("/admin/hello") public String adminHello() { return "Admin Hello!"; } }
8. 测试用户数据
创建测试用户数据,以便进行测试:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import java.util.Collections; import java.util.HashSet; @Component public class DataInitializer implements CommandLineRunner { @Autowired private UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Autowired private PasswordEncoder passwordEncoder; @Override public void run(String... args) throws Exception { // 创建角色 Role adminRole = roleRepository.findByName("ADMIN"); if (adminRole == null) { adminRole = new Role(); adminRole.setName("ADMIN"); roleRepository.save(adminRole); } Role userRole = roleRepository.findByName("USER"); if (userRole == null) { userRole = new Role(); userRole.setName("USER"); roleRepository.save(userRole); } // 创建管理员用户 User adminUser = userRepository.findByUsername("admin"); if (adminUser php== null) { adminUser = new User(); adminUser.setUsername("admin"); adminUser.setPassword(passwordEncoder.encode("admin123")); adminUser.setEnabled(true); adminUser.setRoles(new HashSet<>(Collections.singletonList(adminRole))); userRepository.save(adminUser); } // 创建普通用户 User normalUser = userRepository.findByUsername("user"); if (normalUser == null) { normalUser = new User(); normalUser.setUsername("user"); normalUser.setPassword(passwordEncoder.encode("user123")); normalUser.setEnabled(true); normalUser.setRoles(new HashSet<>(Collections.singletonList(userRole))); userRepository.save(normalUser); } } }
权限控制说明
@PreAuthorize
注解:能在方法级别进行权限控制。例如:
@PreAuthorize("hasRole('ADMIN')") @GetMapping("/admin/hello") public String adminHello() { return "Admin Hello!"; }
角色继承:可以让 ADMIN 角色继承 USER 角色的权限,配置如下:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/public/**").permitAll() .antMatchers("/user/**").hasRole("USER") .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .roleHierarchy(roleHierarchy()); return http.build(); } @Bean public RoleHierarchy roleHierarchy() { RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); return roleHierarchy; }
到此这篇关于SpringBoot实现不同用户不同访问权限的示例代码的文章就介绍到这了,更多相关SpringBoot不同用户不同访问权限内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论