如何让AbstractHttpConfigurer配置优先于本地HttpSecurity代码执行?
问题根源
你调用http.apply(new WebberWebSecurityConfigurerAdapter())时,并未立即执行适配器内的配置逻辑,只是将其注册到HttpSecurity的配置器队列中,要等到http.build()阶段才会按顺序执行所有配置器。而你在代码里先注册适配器,紧接着就配置了anyRequest().authenticated(),导致适配器的配置逻辑在anyRequest之后执行,触发了Spring Security的规则顺序限制——anyRequest必须是最后一条授权规则。
解决方案
方案一:调整适配器执行优先级(推荐,适配通用库场景)
修改WebberWebSecurityConfigurerAdapter,重写getOrder方法让它优先执行,确保库的规则在应用的anyRequest之前添加:
public class WebberWebSecurityConfigurerAdapter extends AbstractHttpConfigurer<WebberWebSecurityConfigurerAdapter, HttpSecurity> { // 设置最高优先级,让库的配置先执行 @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } public void configure(final HttpSecurity http) throws Exception { http .authorizeHttpRequests() .requestMatchers(HEALTH_CHECK_PATH).permitAll(); } }
HttpSecurity会按优先级顺序执行配置器,这样库的放行规则会先被加载,再执行应用的自定义规则和anyRequest限制。
方案二:手动触发适配器配置逻辑(适合临时调试)
在应用的SecurityConfig里,注册适配器后直接调用其configure方法,强制库的配置先执行:
@Configuration public class SecurityConfig { @Bean public SecurityFilterChain config(HttpSecurity http) throws Exception { WebberWebSecurityConfigurerAdapter adapter = new WebberWebSecurityConfigurerAdapter(); // 手动执行适配器配置,跳过队列等待 adapter.configure(http); http .authorizeHttpRequests() .requestMatchers("/", "/request-info", "/test").permitAll() .anyRequest().authenticated(); return http.build(); } }
方案三:统一通过适配器整合规则(规范的Spring Security 6用法)
修改适配器,提供方法让应用传入自定义放行路径,统一管理所有授权规则的顺序:
public class WebberWebSecurityConfigurerAdapter extends AbstractHttpConfigurer<WebberWebSecurityConfigurerAdapter, HttpSecurity> { private final List<String> customPermitPaths = new ArrayList<>(); // 暴露方法接收应用自定义放行路径 public WebberWebSecurityConfigurerAdapter addPermitPaths(String... paths) { customPermitPaths.addAll(Arrays.asList(paths)); return this; } @Override public void configure(final HttpSecurity http) throws Exception { AuthorizationManagerRequestMatcherRegistry registry = http.authorizeHttpRequests(); // 1. 先添加库的默认放行规则 registry.requestMatchers(HEALTH_CHECK_PATH).permitAll(); // 2. 再添加应用自定义放行规则 if (!customPermitPaths.isEmpty()) { registry.requestMatchers(customPermitPaths.toArray(new String[0])).permitAll(); } // 3. 最后设置全局认证规则 registry.anyRequest().authenticated(); } }
应用侧配置简化为:
@Configuration public class SecurityConfig { @Bean public SecurityFilterChain config(HttpSecurity http) throws Exception { http.apply(new WebberWebSecurityConfigurerAdapter() .addPermitPaths("/", "/request-info", "/test")); return http.build(); } }
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

