Spring Security多认证配置按URL匹配不生效及栈溢出问题咨询
问题1:初始配置只有第一套生效的原因
Spring Security 多WebSecurityConfigurerAdapter配置的执行逻辑是按@Order优先级从高到低匹配请求,一旦某套配置匹配到当前请求,后续优先级更低的配置会直接跳过。
你初始的第一套OauthOktaConfigurationAdapter没有通过requestMatchers/antMatcher指定专属的拦截路径,默认会拦截所有请求,因此所有请求都会走第一套认证逻辑,第二套StandardSecurityConfigurationAdapter永远不会被触发。你后续修改后的版本给每个配置都加了requestMatchers限定路径,已经解决了这个问题。
问题2:修改配置后出现的浏览器弹登录框+栈溢出问题的解决方法
栈溢出原因与修复
你在StandardSecurityConfigurationAdapter中注入了全局的AuthenticationManager,而Spring Security中全局的AuthenticationManager本身会委托各个子配置的AuthenticationManager进行认证,形成了循环调用,最终触发栈溢出。
修复方案:
- 删除根配置类中暴露全局
AuthenticationManager的@Bean方法 - 不要在子配置类中注入全局
AuthenticationManager,改为在子配置类内部构建本地专属的AuthenticationManager,示例代码如下:
@Configuration @Order(3) public static class StandardSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter { @Value("${algo.http.auth-app-id-header-name}") private String appIdRequestHeaderName; @Value("${algo.http.auth-api-key-header-name}") private String apiKeyRequestHeaderName; // 配置你自定义的请求头认证逻辑Provider @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(customRequestHeaderAuthProvider()); } @Override protected void configure(HttpSecurity http) throws Exception { http.cors(); http.csrf().disable(); // 禁用基础认证,防止浏览器弹登录框 http.httpBasic().disable(); // 自定义401响应,避免返回WWW-Authenticate头触发浏览器弹框 http.exceptionHandling() .authenticationEntryPoint((request, response, authException) -> { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write("{\"code\":401,\"msg\":\"未授权\"}"); }); http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and().addFilter(initAuthenticationFilter()) .requestMatchers(matchers -> matchers.antMatchers("/api/**")) .authorizeRequests(authz -> authz.anyRequest().authenticated()); } private RequestHeaderAuthenticationFilter initAuthenticationFilter() throws Exception { RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter(appIdRequestHeaderName, apiKeyRequestHeaderName); filter.setContinueFilterChainOnUnsuccessfulAuthentication(false); // 调用父类方法获取当前子配置专属的AuthenticationManager filter.setAuthenticationManager(authenticationManager()); return filter; } // 替换为你自己实现的请求头认证Provider @Bean public AuthenticationProvider customRequestHeaderAuthProvider() { return new CustomRequestHeaderAuthProvider(); } }
浏览器弹登录框原因与修复
浏览器弹出登录框是因为Spring Security默认的401响应会携带WWW-Authenticate: Basic头,浏览器识别到这个头就会触发基础认证弹窗。
修复方案:
在所有三个子配置的configure(HttpSecurity http)方法中都添加http.httpBasic().disable(),同时可以参考上面的代码自定义401响应内容,避免返回触发弹框的响应头。
内容的提问来源于stack exchange,提问作者CrYoSoRe

