SpringSecurity(二)——授权实现

一、授权基本思路

在SpringSecurity中,会使用默认的FilterSecurityInterceptor来进行权限校验。在 FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication,然后获取其中的 权限信息。当前用户是否拥有访问当前资源所需的权限。

所以我们在项目中只需要把当前登录用户的权限信息也存入Authentication。然后设置我们的资源所需 要的权限即可

二、实现过程

(1)开启相关配置

java 复制代码
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig{
    .....
}

然后就可以使用对应的注解。@PreAuthorize在各接口

java 复制代码
@RestController
public class HelloController {

     @RequestMapping("/hello")
     @PreAuthorize("hasAuthority('test')")
     public String hello(){
         return "hello";
     }
 }

(2)自定义LoginUser,封装权限信息

我们之前定义了UserDetails的实现类LoginUser,想要让其能封装权限信息就要对其进行修改。

java 复制代码
@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;

    //返回权限
    @Override
    public 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;
    }

    //获取密码
    @Override
    public String getPassword() {
        return user.getPassword();
    }

    //获取用户名
    @Override
    public String getUsername() {
        return user.getUserName();
    }

    //判断账号是否未过期
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    //判断账号是否没有锁定
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    //判断账号是否没有超时
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    //判断账号是否可用
    @Override
    public boolean isEnabled() {
        return true;
    }

}

(3)从数据库查询权限信息

RBAC模型

我们可以在UserDetailsServiceImpl中去调用该mapper的方法查询权限信息封装到LoginUser对象 中即可。

java 复制代码
@Service
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Override
    public 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);
    }
}
相关推荐
忧郁的蛋~11 分钟前
.NET异步编程中内存泄漏的终极解决方案
开发语言·前端·javascript·.net
sp4215 分钟前
漫谈 Java 轻量级的模板技术:从字符串替换到复杂模板
java·后端
2301_7951672016 分钟前
玩转Rust高级应用. ToOwned trait 提供的是一种更“泛化”的Clone 的功能,Clone一般是从&T类型变量创造一个新的T类型变量
开发语言·后端·rust
水月wwww21 分钟前
vue学习之组件与标签
前端·javascript·vue.js·学习·vue
你才是向阳花29 分钟前
如何用Python实现飞机大战小游戏
开发语言·python·pygame
9523630 分钟前
数据结构-链表
java·数据结构·学习
喵手32 分钟前
Java线程通信:多线程程序中的高效协作!
java
合作小小程序员小小店34 分钟前
web网页开发,在线%商城,电商,商品购买%系统demo,基于vscode,apache,html,css,jquery,php,mysql数据库
开发语言·前端·数据库·mysql·html·php·电商
顾安r36 分钟前
11.8 脚本网页 塔防游戏
服务器·前端·javascript·游戏·html
草莓熊Lotso42 分钟前
C++ 方向 Web 自动化测试实战:以博客系统为例,从用例到报告全流程解析
前端·网络·c++·人工智能·后端·python·功能测试