Skip to main content

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

  1. 配置类

    @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();
    }
    }
  2. 自定义类实现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 注解

image-20230402162026994

三个接口

@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)

方法执行之后进行校验