• 软件:1158
  • 资讯:35555|
  • 收录网站:95206|

IT精英团

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

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

浏览次数:
评论次数:
编辑: mob604756f80175
信息来源: 51CTO博客
更新日期: 2021-05-04 09:45:35
摘要

Spring Security 实战干货:动态权限控制还能更加简单一些,mob604756f80175的博客原创的Java文章。

  • 资讯详情

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

基于表达式的访问控制

httpSecurity.authorizeRequests()
    .anyRequest()
    .access("hasRole('admin')")

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

基于Bean的访问控制表达式

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

/**
 * 角色检查器接口.
 *
 * @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的角色检查,最好这里做个缓存:

/**
 * 基于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

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

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

路径参数

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

/**
 * 角色检查器接口.
 *
 * @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);
}

对应的配置为:

httpSecurity.authorizeRequests()
    .antMatchers("/foo/{id}/**")
    .access("@roleChecker.check(authentication,#id)")

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

总结

这种表达式的动态权限控制比之前的方式更加容易掌握和理解。但是它也有它的局限性,比如表达式中的方法中的参数类型比较单一。而通过FilterInvocationSecurityMetadataSource的方式则更加强大,可以自定义一些访问决策,适合更加复杂的场景。我是:码农小胖哥,多多关注,分享更多原创编程干货。

标签: Java
忙里偷闲又把自己的JWT实现改进了一下
« 上一篇
返回列表
下一篇 »
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
你会是第一个来这里评论的人吗?
最近发布资讯
更多