如何在Spring Security中创建自定义Authorization Filter以支持ABAC授权
Spring Security ABAC授权实现相关问题解答
一、自定义AuthorizationFilter的标准化实现方式
Spring Security 提供了两种官方推荐的标准化方案来实现自定义授权逻辑,适配你的ABAC场景:
方案1:扩展
AuthorizationManager(官方优先推荐)
不需要从零编写完整的Filter,Spring Security 5.5+ 版本默认的AuthorizationFilter已经提供了授权过滤器的通用能力,你只需要实现AuthorizationManager<RequestAuthorizationContext>接口,将已有的ABAC授权逻辑嵌入即可,示例代码如下:@Component public class AbacAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> { // 注入你已经实现的ABAC逻辑服务 private final AbacRuleService abacRuleService; public AbacAuthorizationManager(AbacRuleService abacRuleService) { this.abacRuleService = abacRuleService; } @Override public AuthorizationDecision check(Supplier<Authentication> authSupplier, RequestAuthorizationContext context) { // 获取主体信息 Authentication auth = authSupplier.get(); // 获取资源、操作、环境属性 HttpServletRequest request = context.getRequest(); String resourcePath = request.getRequestURI(); String operateMethod = request.getMethod(); Map<String, String[]> envParams = request.getParameterMap(); // 调用ABAC校验逻辑 boolean isAllowed = abacRuleService.checkPermission(auth.getPrincipal(), resourcePath, operateMethod, envParams); return new AuthorizationDecision(isAllowed); } }之后直接在安全配置中注册该管理器即可:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, AbacAuthorizationManager abacManager) throws Exception { return http // 省略其他如登录、CSRF等配置 .authorizeHttpRequests(auth -> auth.anyRequest().access(abacManager)) .build(); } }方案2:自定义独立授权Filter
如果你确实需要完整控制过滤器的执行逻辑,可以继承OncePerRequestFilter实现自定义授权过滤器,再通过Spring Security提供的过滤器链注册方法插入到正确位置:
自定义Filter示例:@Component public class AbacAuthorizationFilter extends OncePerRequestFilter { private final AbacRuleService abacRuleService; public AbacAuthorizationFilter(AbacRuleService abacRuleService) { this.abacRuleService = abacRuleService; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); // 未登录的情况可以直接放行或抛出异常,由认证流程处理 if (auth == null || !auth.isAuthenticated()) { chain.doFilter(request, response); return; } // 执行ABAC校验 boolean isAllowed = abacRuleService.checkPermission(auth.getPrincipal(), request.getRequestURI(), request.getMethod()); if (!isAllowed) { response.setStatus(HttpServletResponse.SC_FORBIDDEN); return; } chain.doFilter(request, response); } }注册到过滤器链,放在默认授权过滤器之前即可:
http.addFilterBefore(abacAuthorizationFilter, AuthorizationFilter.class);
二、Security上下文的对象设置说明
不需要额外定义类似Authentication的独立对象存入SecurityContext:
Authentication就是Spring Security标准的主体信息载体,ABAC所需的用户属性可以直接扩展存储:比如自定义UserDetails实现类新增部门、职级、权限标签等属性,或者将动态属性存入Authentication的details字段即可。- 如果是请求级别的临时授权参数,直接存入
HttpServletRequest的属性中即可,不需要存入SecurityContext,避免线程复用带来的上下文污染问题。
内容的提问来源于stack exchange,提问作者Anuja Barve
相关产品推荐
相关产品推荐

