Spring Security动态权限越来越容易了

举报
码农小胖哥 发表于 2022/04/01 01:30:42 2022/04/01
【摘要】 Spring Security 5.6 发布有些时间了。随着Spring Boot 2.6的发布Spring Security 5.6终于有机会上生产了。在Spring Security 5.6中动态权限控制更加清晰简单了,今天就带你来尝尝鲜。 节奏快起来 是的,现在不光Java在提速,连Spring的速度现在也提起来了。...

d436a614ae3cfea40bacdebce54ca3c7.gif

Spring Security 5.6 发布有些时间了。随着Spring Boot 2.6的发布Spring Security 5.6终于有机会上生产了。在Spring Security 5.6中动态权限控制更加清晰简单了,今天就带你来尝尝鲜。

节奏快起来

是的,现在不光Java在提速,连Spring的速度现在也提起来了。新的东西越来越多。现在Spring Boot的版本生命周期缩短了到半年,每半年就发一个版本。而Spring Security的版本生命周期也有类似的改变。

9d0161bede4ae5b2c396f1e2f47a5dbd.png Spring Security版本生命周期

作为Spring工程师而言,学习的节奏也不得不加快了。这是一个残酷的事实,这里简单提一下,好了,我们回归正题。

Spring Security动态权限

如果你的接口权限非常稳定,我推荐你使用注解方式;反之,使用动态权限控制。动态权限控制更加灵活和贴近现实,但是开发成本也高。

最常见的方式

之前Spring Security提供的动态权限控制门槛挺高的,需要实现一个FilterInvocationSecurityMetadataSource接口。而且目前网上大部分的教程还是这样的,因此就不再赘述了。

基于SpEL方式

上面方法的成本太高了,因此在后续的版本中基于Spring表达式语言又提供了一种可以实现动态权限的方式。这种方式有一定的要求:

  1. 首先要有一个Spring Bean。

  2. 这个Spring Bean必须包含一个公开方法;返回值为布尔值;参数列表有两个参数,第一个参数是当前认证的信息Authentication,第二个参数是当前请求HttpServletRequest。很好理解就是拿着当前请求去和当前认证信息中包含的角色进行访问控制判断。

  3. 然后按照@bean名称.方法名(authentication,request)的格式配置到HttpSecurity 对象中。

伪代码是这样的:

@Bean
    RoleChecker roleChecker() {
        // 包含了一个符合SpEL要求的方法
        //  boolean check(Authentication authentication, HttpServletRequest request);
        return new JdbcRoleChecker();
    }

配置到HttpSecurity:

httpSecurity.authorizeRequests()
                .anyRequest()
                .access("@roleChecker.check(authentication,request)");

在Spring Security 5.6之前这样做是最简单的,需要你深入了解Spring Security和SpEL才行。

AuthorizationManager

Spring Security 5.6 增加了一个新的授权管理器接口AuthorizationManager<T>,它让动态权限的控制接口化了。它用来检查当前认证信息Authentication是否可以访问特定对象T。上面的RoleChecker不就是AuthorizationManager<HttpServletRequest>么?AuthorizationManager将这种访问决策抽象的更加泛化。

@FunctionalInterface
public interface AuthorizationManager<T> {
 
 default void verify(Supplier<Authentication> authentication, T object) {
  AuthorizationDecision decision = check(authentication, object);
        // 授权决策没有经过允许就403
  if (decision != null && !decision.isGranted()) {
   throw new AccessDeniedException("Access Denied");
  }
        // todo 没有null 的情况
 }

    // 钩子方法。
 @Nullable
 AuthorizationDecision check(Supplier<Authentication> authentication, T object);

}

在Spring Security 5.6中,我们就可以这样去实现了:

httpSecurity.authorizeHttpRequests()
                .anyRequest()
                .access((authenticationSupplier, requestAuthorizationContext) -> {
                    // 当前用户的权限信息 比如角色
                    Collection<? extends GrantedAuthority> authorities = authenticationSupplier.get().getAuthorities();
                    // 当前请求上下文
                    // 我们可以获取携带的参数
                    Map<String, String> variables = requestAuthorizationContext.getVariables();
                    // 我们可以获取原始request对象
                    HttpServletRequest request = requestAuthorizationContext.getRequest();
                    //todo 根据这些信息 和业务写逻辑即可 最终决定是否授权 isGranted
                    boolean isGranted = true;
                    return new AuthorizationDecision(isGranted);
                });

这样门槛是不是低多了呢?你还会选择每次修改权限都要打jar包发版的注解权限控制吗?

Spring Boot 2.6正式发布,Spring Boot 2.4停止维护

2021-11-19

f521ba4d6374ec93355ac1a0658d21ca.png

JSON序列化和反序列化还有这种玩法

2021-11-18

02cb64453f2a6e2fd42126cb32be4227.png

OAuth2.0中的scope和RBAC中的role有什么关系

2021-11-16

c0c2be863b8a85d447efffef558abc40.png

Spring OAuth2 授权服务器配置详解

2021-11-15

9caaea4de209a84cc6d93e465b57356c.png

6d3b25c6297894a30fbe49c336d6f96c.gif

文章来源: felord.blog.csdn.net,作者:码农小胖哥,版权归原作者所有,如需转载,请联系作者。

原文链接:felord.blog.csdn.net/article/details/121484471

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。