springSecurity权限控制

权限控制:不同的用户可以使用不同的功能。

我们不能在前端判断用户权限来控制显示哪些按钮,因为这样,有人会获取该功能对应的接口,就不需要通过前端,直接发送请求实现功能了。所以需要在后端进行权限判断。(前端防君子,后端防小人。

授权流程:springSecurity会默认使用FilterSecurityInterceptor进行权限校验,会从SecurityContextHolder中获取authentication,获取权限信息进行判断。

所以需要我们做的就是把用户的权限信息存入authentication。

那么SecurityContextHolder中的权限信息是从哪里获取的呢,前面SecurityContextHolder中的认证用户信息是从redis中获取的,权限信息也一样。

我们先说说权限控制的方案:1、springSecurity提供注解;2、配置

注解权限控制是我们经常用的,我就只说这个方案了。

使用权限控制注解,需要在SecurityConfig配置类中开启配置:

@EnableGlobalMethodSecurity(prePostEnabled = true)

java 复制代码
@Configuration
//开启权限控制注解
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
     .....
}

我们能用的权限控制注解有很多,但真正经常用的只有@PreAuthorize就是在访问之前进行权限判断。写在controller层的请求方法上。

@PreAuthorize("hasAuthority('test')")

这里其实是去调用hasAuthority方法去判读权限,返回true即有权限。test为权限名

java 复制代码
@RestController
@RequestMapping
public class HelloController {
    @GetMapping("/hello")
    //这里其实是去调用hasAuthority方法去判读权限,返回true即有权限.test为权限名,这里只能填一个权限
    @PreAuthorize("hasAuthority('test')")
    public String hello(){
        return "hello";
    }

至于 权限名的定义和权限内容的定义 在后面定义。

注解类方法:

@PreAuthorize("hasAuthority('权限名')")

除了前面用的hasAuthority方法外,还有其他的校验方法,当然我们也可以自定义校验方法。

hasAuthority('')方法:只能填一个权限。

hasAnyAuthority('','','')方法:可以传入多个权限,其中用户有任意一个权限都可以访问。

hasRole('')方法:要求有对应角色才可以访问。它内部会把我们传入的角色参数拼接上 ROLE_ 后在去比较,所以需要对用户的权限也要有 ROLE_ 这个前缀。

hasAnyRole('','','')方法:要求有对应任意角色才可以访问。它内部也会把我们传入的角色参数拼接上 ROLE_ 后在去比较,所以需要对用户的权限也要有 ROLE_ 这个前缀。

同时权限是实体类User类的属性:

java 复制代码
@Data
@NoArgsConstructor
//@AllArgsConstructor
public class LoginUser implements UserDetails {

    //需要定义User对象来封装用户信息。
    private User user;

    //该用户的权限信息
    private List<String> permissions;
    public LoginUser(User user, List<String> permissions) {
        this.user = user;
        this.permissions = permissions;
    }

    //问题:当我们把logUser存入redis中时,redis默认不会把SimpleGrantedAuthority对象序列化。
    //解决:我们不需要把SimpleGrantedAuthority存入redis,我们只需把权限信息permissions存入即可
    //通过permissions反序列化即可获取authorities,所以需要忽略SimpleGrantedAuthority,不要对它序列化
    @JSONField(serialize = false)
    private List<SimpleGrantedAuthority> authorities;
    @Override //实际springSecurity获取权限信息是调用的该方法,重写该方法。
    public Collection<? extends GrantedAuthority> getAuthorities() {
        //优化:如果每次获取权限都进行集合转换,有点浪费。我们只第一次去集合转换,后续获取直接返回之前转换好的
        //即把List<SimpleGrantedAuthority> authorities定义为成员变量。
        if(authorities!=null){
            return authorities;
        }
        authorities = permissions.stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
        return authorities;
    }
}

然后去数据库中查询用户权限:

到数据库中查询权限信息:

RBAC权限模型(Role-Based Access Control):基于角色的权限控制。这是目前最常被开发者使用也是相对易用、通用权限模型。

在数据库中,我们会创建一个用户表,一个权限表(记录着权限功能说明和权限名),一个用户可以有多个权限,不好表达,所以我们又引入了一个角色表,里面有很多角色,在创建个角色权限管理表,每种角色对应不同的多种功能,为角色赋予不同的权限。比如:图书馆管理系统中的角色:图书管理员(权限:添加、查询、删除等等);借阅者(权限:查询、借阅)。同时,一个用户可能会有多种身份,需要将用户与角色关联起来。

这就是RBAC模型(最少都是5张表)

5表联合查询用户权限:role为角色表,menu为菜单表(可以理解为权限表)

XML 复制代码
<mapper namespace="org.example.springSecurity.mapper.MenuMapper">
    <select id="selectPermsByUserId" resultType="java.lang.String">
        select
        distinct m.perms
        from sys_user_role ur
        Left join `sys_role` r on ur.role_id = r.id
        Left join `sys_role_menu` rm on ur.role_id = rm.role_id
        Left join `sys_menu` m on m.id = rm.menu_id
        where
        user_id = #{userId}
        and r.status = 0
        and m.status = 0
    </select>
</mapper>
相关推荐
佛祖让我来巡山3 天前
小明网站双登录系统实现——微信授权登录+用户名密码登录完整指南
oauth2·springsecurity·微信授权登录
佛祖让我来巡山3 天前
Spring Security 鉴权流程与过滤器链深度剖析
springsecurity·authenticationmanager
佛祖让我来巡山4 天前
大型项目基于Spring Security的登录鉴权与数据权限控制完整方案
springsecurity·保姆级鉴权·大型项目登录认证
佛祖让我来巡山4 天前
Spring Security前后端分离接入流程保姆级教程
权限校验·springsecurity·登录认证
佛祖让我来巡山4 天前
Spring Security 认证流程闭环与调用链路详解
springsecurity·authenticationmanager
佛祖让我来巡山5 天前
小明的Spring Security入门到深入实战
springsecurity
佛祖让我来巡山6 天前
⚠️登录认证功能的成长过程:整体概述
安全·登录·springsecurity·登录认证·认证授权
码熔burning3 个月前
Spring Security 深度学习(六): RESTful API 安全与 JWT
安全·spring·restful·springsecurity
A尘埃3 个月前
SpringSecurity版本的不同配置
认证·springsecurity·安全配置·不同版本
世纪摆渡人4 个月前
SpringSecurity-SpringSecurity入门介绍
springsecurity