You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security运行时如何动态增删antMatchers及配置角色映射?

Spring Security 运行时动态修改HttpSecurity配置的实现方案

默认WebSecurityConfigurerAdapter的configure(HttpSecurity http)方法仅在Spring容器初始化阶段执行一次,生成的安全配置会固化到过滤器链中,原生不支持运行时直接修改。要实现antMatchers规则增删、配置重写、角色映射调整等动态操作,可以采用以下两种成熟方案:


方案一:动态鉴权过滤器实现(无侵入、推荐)

放弃在configure方法中硬编码固定的antMatchers规则,通过自定义权限校验逻辑读取动态规则,运行时修改规则存储即可即时生效,适合绝大多数动态权限场景。

实现步骤:

  • 自定义AccessDecisionManager鉴权决策管理器,所有路径的权限校验逻辑全部在该类中实现,规则存储在内存缓存/数据库中
  • 在HttpSecurity配置中替换默认的决策管理器,所有请求走自定义动态鉴权逻辑

代码示例

自定义动态决策管理器:

public class DynamicAccessDecisionManager implements AccessDecisionManager {
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) 
            throws AccessDeniedException, InsufficientAuthenticationException {
        HttpServletRequest request = ((FilterInvocation) object).getRequest();
        String requestUri = request.getRequestURI();
        String method = request.getMethod();

        // 此处从缓存/数据库读取当前路径对应的所需角色、是否放行等规则
        // 自定义校验逻辑:匹配路径规则、比对用户权限,校验不通过直接抛出异常即可
        boolean hasPermission = checkPermission(requestUri, method, authentication);
        if (!hasPermission) {
            throw new AccessDeniedException("无访问权限");
        }
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}

配置替换默认决策管理器:

@EnableWebSecurity
public class WebSecurityConfigAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                // 替换为自定义动态决策管理器
                .accessDecisionManager(dynamicAccessDecisionManager())
                .and()
                .formLogin()
                // 其余原有配置(csrf、跨域、登录退出等)按需保留
                .and().csrf().disable();
    }

    @Bean
    public DynamicAccessDecisionManager dynamicAccessDecisionManager() {
        return new DynamicAccessDecisionManager();
    }
}
  • 优势:不需要修改Spring Security原生过滤器链结构,规则修改后秒级生效,性能损耗极低。
  • 适用场景:antMatchers规则增删、角色-路径映射调整等常规动态权限需求。

方案二:动态替换过滤器链(支持全量重写配置)

如果需要完全重写安全配置(比如修改登录逻辑、csrf规则等超出权限匹配的场景),可以通过动态替换Spring Security核心的SecurityFilterChain实现配置全量刷新。

实现步骤:

  • 自定义持有SecurityFilterChain的容器类,对外暴露刷新配置的方法
  • 替换默认的FilterChainProxy,每次请求优先从自定义容器读取最新的过滤器链
  • 触发配置刷新时,重新通过HttpSecurity构建新的过滤器链,替换容器内的旧实例即可

代码示例

// 自定义过滤器链持有容器
@Component
public class DynamicSecurityFilterChainHolder {
    private volatile List<SecurityFilterChain> filterChains;

    public List<SecurityFilterChain> getFilterChains() {
        return filterChains;
    }

    // 对外暴露的配置刷新方法
    public void refreshConfig(Consumer<HttpSecurity> configCustomizer) throws Exception {
        // 从Spring上下文获取HttpSecurity实例
        HttpSecurity http = ApplicationContextUtils.getBean(HttpSecurity.class);
        // 传入自定义配置逻辑构建新的过滤器链
        configCustomizer.accept(http);
        SecurityFilterChain newChain = http.build();
        this.filterChains = Collections.singletonList(newChain);
    }
}

替换默认FilterChainProxy:

@Bean
public FilterChainProxy springSecurityFilterChain(DynamicSecurityFilterChainHolder chainHolder) {
    return new FilterChainProxy(chainHolder.getFilterChains()) {
        @Override
        public List<Filter> getFilters(String url) {
            // 每次请求都读取最新的过滤器链
            super.setFilterChains(chainHolder.getFilterChains());
            return super.getFilters(url);
        }
    };
}
  • 注意:刷新配置时会短暂影响请求处理,需要做好并发控制,且仅开放给超级管理员操作,避免出现安全漏洞。
  • 适用场景:需要全量重写安全配置的极端场景。

版本适配说明

Spring Security 5.7+版本已废弃WebSecurityConfigurerAdapter,推荐使用SecurityFilterChain Bean的方式定义配置,上述两种方案依然适配,仅需将原有configure方法内的逻辑迁移到SecurityFilterChain构建方法即可。

内容的提问来源于stack exchange,提问作者gogagubi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 22:18:01