Spring Security 中的四种权限控制方式

Spring Security 中对于权限控制默认已经提供了不少了,可是,一个优秀的框架必须具有良好的扩展性,刚好,Spring Security 的扩展性就很是棒,咱们既可使用 Spring Security 提供的方式作受权,也能够自定义受权逻辑。一句话,你想怎么玩均可以!java

今天松哥来和你们介绍一下 Spring Security 中四种常见的权限控制方式。数据库

  • 表达式控制 URL 路径权限
  • 表达式控制方法权限
  • 使用过滤注解
  • 动态权限

四种方式,咱们分别来看。后端

本文是 Spring Security 系列第 30 篇,阅读前面文章有助于更好的理解本文:跨域

  1. 挖一个大坑,Spring Security 开搞!
  2. 松哥手把手带你入门 Spring Security,别再问密码怎么解密了
  3. 手把手教你定制 Spring Security 中的表单登陆
  4. Spring Security 作先后端分离,咱就别作页面跳转了!通通 JSON 交互
  5. Spring Security 中的受权操做原来这么简单
  6. Spring Security 如何将用户数据存入数据库?
  7. Spring Security+Spring Data Jpa 强强联手,安全管理只有更简单!
  8. Spring Boot + Spring Security 实现自动登陆功能
  9. Spring Boot 自动登陆,安全风险要怎么控制?
  10. 在微服务项目中,Spring Security 比 Shiro 强在哪?
  11. SpringSecurity 自定义认证逻辑的两种方式(高级玩法)
  12. Spring Security 中如何快速查看登陆用户 IP 地址等信息?
  13. Spring Security 自动踢掉前一个登陆用户,一个配置搞定!
  14. Spring Boot + Vue 先后端分离项目,如何踢掉已登陆用户?
  15. Spring Security 自带防火墙!你都不知道本身的系统有多安全!
  16. 什么是会话固定攻击?Spring Boot 中要如何防护会话固定攻击?
  17. 集群化部署,Spring Security 要如何处理 session 共享?
  18. 松哥手把手教你在 SpringBoot 中防护 CSRF 攻击!so easy!
  19. 要学就学透彻!Spring Security 中 CSRF 防护源码解析
  20. Spring Boot 中密码加密的两种姿式!
  21. Spring Security 要怎么学?为何必定要成体系的学习?
  22. Spring Security 两种资源放行策略,千万别用错了!
  23. 松哥手把手教你入门 Spring Boot + CAS 单点登陆
  24. Spring Boot 实现单点登陆的第三种方案!
  25. Spring Boot+CAS 单点登陆,如何对接数据库?
  26. Spring Boot+CAS 默认登陆页面太丑了,怎么办?
  27. 用 Swagger 测试接口,怎么在请求头中携带 Token?
  28. Spring Boot 中三种跨域场景总结
  29. Spring Boot 中如何实现 HTTP 认证?

1.表达式控制 URL 路径权限

首先咱们来看第一种,就是经过表达式控制 URL 路径权限,这种方式松哥在以前的文章中实际上和你们讲过,这里咱们再来稍微复习一下。安全

Spring Security 支持在 URL 和方法权限控制时使用 SpEL 表达式,若是表达式返回值为 true 则表示须要对应的权限,不然表示不须要对应的权限。提供表达式的类是 SecurityExpressionRoot:session

能够看到,SecurityExpressionRoot 有两个实现类,表示在应对 URL 权限控制和应对方法权限控制时,分别对 SpEL 所作的拓展,例如在基于 URL 路径作权限控制时,增长了 hasIpAddress 选项。框架

咱们来看下 SecurityExpressionRoot 类中定义的最基本的 SpEL 有哪些:前后端分离

能够看到,这些都是该类对应的表达式,这些表达式我来给你们稍微解释下:函数

表达式 备注
hasRole 用户具有某个角色便可访问资源
hasAnyRole 用户具有多个角色中的任意一个便可访问资源
hasAuthority 相似于 hasRole
hasAnyAuthority 相似于 hasAnyRole
permitAll 通通容许访问
denyAll 通通拒绝访问
isAnonymous 判断是否匿名用户
isAuthenticated 判断是否定证成功
isRememberMe 判断是否经过记住我登陆的
isFullyAuthenticated 判断是否用户名/密码登陆的
principle 当前用户
authentication 从 SecurityContext 中提取出来的用户对象

这是最基本的,在它的继承类中,还有作一些拓展,我这个我就不重复介绍了。微服务

若是是经过 URL 进行权限控制,那么咱们只须要按照以下方式配置便可:

protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("admin")
            .antMatchers("/user/**").hasAnyRole("admin", "user")
            .anyRequest().authenticated()
            .and()
            ...
}

这里表示访问 /admin/** 格式的路径须要 admin 角色,访问 /user/** 格式的路径须要 admin 或者 user 角色。

2.表达式控制方法权限

固然,咱们也能够经过在方法上添加注解来控制权限。

在方法上添加注解控制权限,须要咱们首先开启注解的使用,在 Spring Security 配置类上添加以下内容:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    ...
    ...
}

这个配置开启了三个注解,分别是:

  • @PreAuthorize:方法执行前进行权限检查
  • @PostAuthorize:方法执行后进行权限检查
  • @Secured:相似于 @PreAuthorize

这三个结合 SpEL 以后,用法很是灵活,这里和你们稍微分享几个 Demo。

@Service
public class HelloService {
    @PreAuthorize("principal.username.equals('javaboy')")
    public String hello() {
        return "hello";
    }

    @PreAuthorize("hasRole('admin')")
    public String admin() {
        return "admin";
    }

    @Secured({"ROLE_user"})
    public String user() {
        return "user";
    }

    @PreAuthorize("#age>98")
    public String getAge(Integer age) {
        return String.valueOf(age);
    }
}
  1. 第一个 hello 方法,注解的约束是,只有当前登陆用户名为 javaboy 的用户才能够访问该方法。
  2. 第二个 admin 方法,表示访问该方法的用户必须具有 admin 角色。
  3. 第三个 user 方法,表示方法该方法的用户必须具有 user 角色,可是注意 user 角色须要加上 ROLE_ 前缀。
  4. 第四个 getAge 方法,表示访问该方法的 age 参数必须大于 98,不然请求不予经过。

能够看到,这里的表达式仍是很是丰富,若是想引用方法的参数,前面加上一个 # 便可,既能够引用基本类型的参数,也能够引用对象参数。

缺省对象除了 principal ,还有 authentication(参考第一小节)。

3.使用过滤注解

Spring Security 中还有两个过滤函数 @PreFilter 和 @PostFilter,能够根据给出的条件,自动移除集合中的元素。

@PostFilter("filterObject.lastIndexOf('2')!=-1")
public List<String> getAllUser() {
    List<String> users = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        users.add("javaboy:" + i);
    }
    return users;
}
@PreFilter(filterTarget = "ages",value = "filterObject%2==0")
public void getAllAge(List<Integer> ages,List<String> users) {
    System.out.println("ages = " + ages);
    System.out.println("users = " + users);
}
  • 在 getAllUser 方法中,对集合进行过滤,只返回后缀为 2 的元素,filterObject 表示要过滤的元素对象。
  • 在 getAllAge 方法中,因为有两个集合,所以使用 filterTarget 指定过滤对象。

4.动态权限

动态权限主要经过重写拦截器和决策器来实现,这个我在 vhr 的文档中有过详细介绍,你们在公众号【江南一点雨】后台回复 888 能够获取文档,我就再也不赘述了。

5.小结

好啦,今天就喝小伙伴们稍微聊了一下 Spring Security 中的受权问题,固然这里还有不少细节,后面松哥再和你们一一细聊。

若是小伙伴们以为有收获,记得点个在看鼓励下松哥哦~

相关文章
相关标签/搜索