Spring Security配置仅特定URI触发Oauth2Login 其余未认证请求返回401
解决方案
核心思路
当前配置同时启用了OAuth2登录和OAuth2资源服务器能力,Spring Security默认会根据请求的Accept头决定未认证时是返回重定向响应还是401响应。要实现按URI路径区分处理逻辑,只需要替换默认的认证入口点规则即可:
- 自定义组合式
ServerAuthenticationEntryPoint,匹配指定URI时走OAuth2登录重定向逻辑 - 其余未携带
Authorization头的请求直接返回401响应 - 需将OAuth2登录流程依赖的回调路径纳入重定向白名单,避免登录流程中断
完整配置代码
import org.springframework.security.config.Customizer; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.oauth2.server.resource.web.server.BearerTokenServerAuthenticationEntryPoint; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.authentication.RedirectServerAuthenticationEntryPoint; import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher; import java.util.List; @Bean SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { // 配置需要触发OAuth2登录重定向的URI列表 List<String> redirectPathPatterns = List.of( // 自定义业务路径,例如前端页面访问路径 "/hub/frontend/**", // OAuth2登录流程必填路径,不可省略 "/oauth2/authorization/**", "/login/oauth2/code/**" ); // OAuth2登录重定向入口点,替换为你自己的客户端注册ID RedirectServerAuthenticationEntryPoint redirectEntryPoint = new RedirectServerAuthenticationEntryPoint("/oauth2/authorization/your-client-id"); // 资源服务器401响应入口点 BearerTokenServerAuthenticationEntryPoint bearerEntryPoint = new BearerTokenServerAuthenticationEntryPoint(); return http .authorizeExchange(exchange -> exchange .pathMatchers("/hub/public/**").permitAll() .anyExchange().authenticated()) .oauth2Login(Customizer.withDefaults()) .oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt) .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable) .csrf(ServerHttpSecurity.CsrfSpec::disable) // 可根据业务需要保留或关闭 .exceptionHandling(exception -> exception .authenticationEntryPoint((exchange, ex) -> { // 按路径匹配选择处理逻辑 PathPatternParserServerWebExchangeMatcher matcher = new PathPatternParserServerWebExchangeMatcher(redirectPathPatterns.toArray(new String[0])); return matcher.matches(exchange) .flatMap(matchResult -> matchResult.isMatch() ? redirectEntryPoint.commence(exchange, ex) : bearerEntryPoint.commence(exchange, ex) ); }) ) .build(); }
备选方案:多过滤器链实现
如果希望逻辑拆分更清晰,也可以配置两个独立的过滤器链:
- 定义优先级更高的过滤器链,仅匹配需要触发重定向的URI,只配置
oauth2Login认证逻辑 - 定义默认过滤器链匹配所有剩余URI,仅配置
oauth2ResourceServer逻辑,未认证时默认返回401
内容的提问来源于stack exchange,提问作者Monta
相关产品推荐
相关产品推荐

