前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security 实战干货:动态权限控制还能更加简单一些

Spring Security 实战干货:动态权限控制还能更加简单一些

作者头像
码农小胖哥
发布2021-04-07 20:41:16
1.4K0
发布2021-04-07 20:41:16
举报

之前在Spring Security动态权限控制的教程中,我们通过自定义FilterInvocationSecurityMetadataSourceAccessDecisionManager两个接口实现了动态权限控制。这里需要我们做的事情比较多,有一定的学习成本。今天来介绍一种更加简单和容易理解的方法实现动态权限控制。

基于表达式的访问控制

代码语言:javascript
复制
httpSecurity.authorizeRequests()
    .anyRequest()
    .access("hasRole('admin')")

这种方式不用多说了吧,我们配置了表达式hasRole('admin')后,Spring Security会调用SecurityExpressionRoothasRole(String role)方法来判断当前用户是否持有角色admin,进而作出是否放行的决策。这种方式除了可以静态的权限控制之外还能够动态的权限控制。

基于Bean的访问控制表达式

Spring Security扩展了对表达式进行了扩展,支持引用任何公开的Spring Bean,假如我们有一个实现下列接口的Spring Bean:

代码语言:javascript
复制
/**
 * 角色检查器接口.
 *
 * @author n1
 * @since 2021 /4/6 16:28
 */
public interface RoleChecker extends InitializingBean {

    /**
     * Check boolean.
     *
     * @param authentication the authentication
     * @param request        the request
     * @return the boolean
     */
    boolean check(Authentication authentication, HttpServletRequest request);
}

基于JDBC的角色检查,最好这里做个缓存:

代码语言:javascript
复制
/**
 * 基于jdbc的角色检查 最好这里做个缓存
 * @author n1
 * @since 2021/4/6 16:43
 */
public class JdbcRoleChecker implements RoleChecker {
    // 系统集合的抽象实现,这里你可以采用更加合理更加效率的方式
    private Supplier<Set<AntPathRequestMatcher>> supplier;


    @Override
    public boolean check(Authentication authentication, HttpServletRequest request) {
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

       // 当前用户的角色集合
        System.out.println("authorities = " + authorities);
        //todo 这里自行实现比对逻辑
       //   supplier.get().stream().filter(matcher -> matcher.matches(request));
       // true false 为是否放行
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(supplier.get(), "function must not be null");
    } 
}

我们就可以这样配置HttpSecurity

代码语言:javascript
复制
httpSecurity.authorizeRequests()
    .anyRequest()
    .access("@roleChecker.check(authentication,request)")

通过RoleChecker中的Authentication我们可以获得当前用户的信息,尤其是权限集。通过HttpServletRequest我们可以获得当前请求的URI。该URI在系统中的权限集和用户的权限集进行交集判断就能作出正确的访问决策。

路径参数

有些时候我们的访问URI中还包含了路径参数,例如/foo/{id}。我们也可以通过基于Bean的访问控制表达式结合具体的id值来控制。这时应该这么写:

代码语言:javascript
复制
/**
 * 角色检查器接口.
 *
 * @author n1
 * @since 2021 /4/6 16:28
 */
public interface RoleChecker extends InitializingBean {

    /**
     * Check boolean.
     *
     * @param authentication the authentication
     * @param request        the request
     * @return the boolean
     */
    boolean check(Authentication authentication, String id);
}

对应的配置为:

代码语言:javascript
复制
httpSecurity.authorizeRequests()
    .antMatchers("/foo/{id}/**")
    .access("@roleChecker.check(authentication,#id)")

这样当/foo/123请求被拦截后,123就会赋值给check方法中的id处理。

总结

这种表达式的动态权限控制比之前的方式更加容易掌握和理解。但是它也有它的局限性,比如表达式中的方法中的参数类型比较单一。而通过FilterInvocationSecurityMetadataSource的方式则更加强大,可以自定义一些访问决策,适合更加复杂的场景。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-04-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农小胖哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基于表达式的访问控制
  • 基于Bean的访问控制表达式
    • 路径参数
    • 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档