springSecurity
相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
自定义用户名密码 xxx 123(不查询数据库)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String password = encoder.encode("123");
auth.inMemoryAuthentication().withUser("qingbomy").password(password).roles("admin");
}
@Bean
PasswordEncoder bCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}
自定义用户名密码,查询数据库
数据库 RBAC 权限SQL
-
配置类
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Bean
PasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
} -
自定义类实现
UserDetailsService
接口
组件的名字要和上面配置文件一样
@Service("userDetailsService")
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Autowired
private UserRoleMapper userRoleMapper;
@Autowired
private RoleMapper roleMapper;
@Override
public UserDetails loadUserByUsername(String username) {
MageUser user = userMapper.selectOne(new QueryWrapper<MageUser>().eq(MageUser.USERNAME, username));
if (user == null) {
throw new UsernameNotFoundException("用户名未找到");
}
List<UserRole> userRoles = userRoleMapper.selectList(new QueryWrapper<UserRole>().eq(UserRole.USER_ID, user.getUserId()));
List<Role> roles = new ArrayList<>();
for (UserRole userRole : userRoles) {
if (userRole == null) {
throw new AuthenticationCredentialsNotFoundException("用户角色为空");
}
roles.add(roleMapper.selectOne(new QueryWrapper<Role>().eq(Role.ROLE_ID, userRole.getRoleId()))) ;
}
StringBuilder sb = new StringBuilder();
//将角色用逗号拼接,一个用户可能有多个角色
if (roles != null) {
for (Role role : roles) {
sb.append(role.getRoleName());
if (roles.indexOf(role) != roles.size()-1) {
sb.append(",");
}
}
}
//模拟查询数据库查询到username的密码和权限
List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(sb.toString());
return new User(user.getUsername(), user.getPassword(), authorities);
}
}
基于注解的权限访问
@Secured 注解
三个接口
@RestController
public class TestController {
@GetMapping("admin")
@Secured({"ROLE_admin"})
public String test(){
return "admin";
}
@GetMapping("user")
@Secured({"ROLE_user"})
public String test1(){
return "user";
}
@GetMapping("test2")
@Secured({"ROLE_user","ROLE_admin"})
public String test2(){
return "user&admin";
}
}
test2 接口的两个角色是“或”的关系,表示 ROLE_user 可以访问 ROLE_admin 也可以访问,"ROLE_user","ROLE_admin"也可以访问
Tips:源码规定,角色名称必须要以ROLE_
作为前缀
@PreAuthorize 注解
先开启 prePostEnabled
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
方法执行之前进行校验
@RestController
public class TestController {
@GetMapping("admin")
// @Secured({"ROLE_admin"})
@PreAuthorize("hasAuthority('ROLE_admin')")
public String test(){
return "admin";
}
@GetMapping("user")
// @Secured({"ROLE_user"})
@PreAuthorize("hasAnyAuthority('ROLE_user')")
public String test1(){
return "user";
}
@GetMapping("test2")
// @Secured({"ROLE_user","ROLE_admin"})
@PreAuthorize("hasAnyRole('ROLE_user','ROLE_admin')")
public String test2(){
return "user&admin";
}
}
@PostAuthorize 注解
先开启 prePostEnabled
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
方法执行之后进行校验