一、授权基本思路
在SpringSecurity中,会使用默认的FilterSecurityInterceptor来进行权限校验。在 FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication,然后获取其中的 权限信息。当前用户是否拥有访问当前资源所需的权限。
所以我们在项目中只需要把当前登录用户的权限信息也存入Authentication。然后设置我们的资源所需 要的权限即可
二、实现过程
(1)开启相关配置
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig{.....
}
然后就可以使用对应的注解。@PreAuthorize在各接口
@RestController
public class HelloController {@RequestMapping("/hello")@PreAuthorize("hasAuthority('test')")public String hello(){return "hello";}}
(2)自定义LoginUser,封装权限信息
我们之前定义了UserDetails的实现类LoginUser,想要让其能封装权限信息就要对其进行修改。
@Data
@NoArgsConstructor
public class LoginUser implements UserDetails{private User user;//查询到的权限列表private List<String> list;public LoginUser(User user, List<String> list) {this.list = list;this.user = user;}//自定义一个权限列表的集合 中转操作@JSONField(serialize = false)List<SimpleGrantedAuthority> authorities;//返回权限@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {if (authorities != null) {return authorities;}authorities = new ArrayList<>();for (String item : list) {SimpleGrantedAuthority authority = new SimpleGrantedAuthority(item);authorities.add(authority);}return authorities;}//获取密码@Overridepublic String getPassword() {return user.getPassword();}//获取用户名@Overridepublic String getUsername() {return user.getUserName();}//判断账号是否未过期@Overridepublic boolean isAccountNonExpired() {return true;}//判断账号是否没有锁定@Overridepublic boolean isAccountNonLocked() {return true;}//判断账号是否没有超时@Overridepublic boolean isCredentialsNonExpired() {return true;}//判断账号是否可用@Overridepublic boolean isEnabled() {return true;}}
(3)从数据库查询权限信息
RBAC模型
我们可以在UserDetailsServiceImpl中去调用该mapper的方法查询权限信息封装到LoginUser对象 中即可。
@Service
public class UserDetailServiceImpl implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate MenuMapper menuMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//1.查询用户信息QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("user_name", username);User user = userMapper.selectOne(queryWrapper);//如果没有查询到用户,就抛出异常if (Objects.isNull(user)) {throw new RuntimeException("用户名或密码错误");}//2.查询用户对应的权限信息
// List<String> list = new ArrayList<>();
// list.add("select");
// list.add("delete");List<String> list = menuMapper.selectPermsByUserId(user.getId());//3.返回UserDetails对象return new LoginUser(user, list);}
}