Spring Security授权服务器permitAll配置不生效问题排查
问题描述
我正在使用Spring Authorization Server,现有两个控制器:/user/**和/client/**。预期需求为:/user/**可公开访问,/client/**仅允许已认证用户访问。我配置了两条过滤器链:一条用于授权服务器,将未认证的/client/**请求重定向到/login;另一条处理登录页重定向。但实际访问/user/**时,却被重定向到/login页面。
配置代码
@Configuration public class WebSecurityConfig { @Order(1) @Bean SecurityFilterChain authServerFilterChain(HttpSecurity http, JwtAuthenticationConverter jwtAuthenticationConverter) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); http.getConfigurer(OAuth2AuthorizationServerConfigurer.class) .oidc(Customizer.withDefaults()); http.exceptionHandling(ex -> ex.defaultAuthenticationEntryPointFor( new LoginUrlAuthenticationEntryPoint("/login"), // redirect all unautheticated /client/** to login new AntPathRequestMatcher("/client/**") )) .oauth2ResourceServer(rs -> rs.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter))); return http.build(); } @Order(2) @Bean SecurityFilterChain defaultFilterChain(HttpSecurity http, CorsConfigurationSource corsConfigurationSource) throws Exception { http .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .csrf(csrf -> csrf.disable()) .cors(cors -> cors.configurationSource(corsConfigurationSource)) .authorizeHttpRequests( req -> req.requestMatchers("/user/**").permitAll() .anyRequest().authenticated()) .formLogin(Customizer.withDefaults()); return http.build(); } @Bean AuthorizationServerSettings authorizationServerSettings() { return AuthorizationServerSettings.builder() .build(); } }
用户端点代码
@Controller @ResponseBody @RequestMapping("/user/") public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService = userService; } @GetMapping() public String hello() { return "Hello from User Controller"; } }
调试日志
2024-09-22T14:23:35.456+05:30 INFO 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2024-09-22T14:23:35.457+05:30 INFO 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2024-09-22T14:23:35.459+05:30 INFO 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms 2024-09-22T14:23:35.492+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing GET /user 2024-09-22T14:23:35.508+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext 2024-09-22T14:23:35.512+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Secured GET /user 2024-09-22T14:23:35.548+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing GET /error 2024-09-22T14:23:35.549+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext 2024-09-22T14:23:35.553+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-1] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8080/login 2024-09-22T14:23:35.580+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-2] o.s.security.web.FilterChainProxy : Securing GET /login 2024-09-22T14:23:35.810+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-3] o.s.security.web.FilterChainProxy : Securing GET /favicon.ico 2024-09-22T14:23:35.811+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-3] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext 2024-09-22T14:23:35.812+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-3] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://localhost:8080/login 2024-09-22T14:23:35.825+05:30 DEBUG 131685 --- [spring-oauth2-auth-server] [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Securing GET /login
问题原因与解决方案
原因分析
从日志可见,/user请求本身已被放行,但后续触发了/error请求,该请求被重定向到登录页。核心问题有两个:
- 默认过滤器链设置了
SessionCreationPolicy.STATELESS无状态会话策略,但表单登录依赖会话管理,两者冲突导致请求处理出错,触发错误页面。 - 授权服务器过滤器链未限定匹配路径,会处理所有请求,包括
/user,虽然未拦截,但后续默认过滤器链的会话配置问题引发了连锁错误。
修复步骤
- 调整会话策略:表单登录需要会话支持,将默认过滤器链的
SessionCreationPolicy.STATELESS改为SessionCreationPolicy.IF_REQUIRED(默认值),或直接移除该配置。 - 限定授权服务器过滤器链的处理路径:让它只处理授权服务器相关路径和
/client/**,避免无关请求进入该链。
修改后的配置代码:
@Configuration public class WebSecurityConfig { @Order(1) @Bean SecurityFilterChain authServerFilterChain(HttpSecurity http, JwtAuthenticationConverter jwtAuthenticationConverter) throws Exception { // 限定该过滤器链仅处理指定路径 http.securityMatcher("/oauth2/**", "/client/**", "/login/**", "/error/**"); OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); http.getConfigurer(OAuth2AuthorizationServerConfigurer.class) .oidc(Customizer.withDefaults()); http.exceptionHandling(ex -> ex.defaultAuthenticationEntryPointFor( new LoginUrlAuthenticationEntryPoint("/login"), new AntPathRequestMatcher("/client/**") )) .oauth2ResourceServer(rs -> rs.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter))); return http.build(); } @Order(2) @Bean SecurityFilterChain defaultFilterChain(HttpSecurity http, CorsConfigurationSource corsConfigurationSource) throws Exception { http // 移除无状态配置,使用默认的IF_REQUIRED支持表单登录 .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) .csrf(csrf -> csrf.disable()) .cors(cors -> cors.configurationSource(corsConfigurationSource)) .authorizeHttpRequests( req -> req.requestMatchers("/user/**").permitAll() .anyRequest().authenticated()) .formLogin(Customizer.withDefaults()); return http.build(); } @Bean AuthorizationServerSettings authorizationServerSettings() { return AuthorizationServerSettings.builder() .build(); } }
内容的提问来源于stack exchange,提问作者kush parsaniya
相关产品推荐
相关产品推荐

