Spring Boot OAuth2配置:未授权请求返回401而非重定向到IDP
解决Spring Boot OAuth2中浏览器请求重定向、API请求返回401的问题
核心思路是区分请求类型:对浏览器发起的页面请求保持重定向到IDP的原有逻辑,对前端JS发起的API请求直接返回401状态码,避免触发IDP的CORS问题。
1. 自定义AuthenticationEntryPoint
创建一个自定义的认证入口点,根据请求特征判断是API请求还是浏览器页面请求,分别处理:
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import org.springframework.stereotype.Component; import java.io.IOException; @Component public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { // 复用默认的重定向逻辑,替换成你的IDP注册ID private final AuthenticationEntryPoint delegate = new LoginUrlAuthenticationEntryPoint("/oauth2/authorization/your-idp-registration-id"); @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { // 判断是否为API请求:可根据路径前缀、请求头调整逻辑 boolean isApiRequest = request.getRequestURI().startsWith("/api/") && !"/api/oauth2/login".equals(request.getRequestURI()) || "application/json".equals(request.getHeader("Accept")); if (isApiRequest) { // API请求直接返回401 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); } else { // 浏览器页面请求,走默认的IDP重定向逻辑 delegate.commence(request, response, authException); } } }
2. 修改SecurityFilterChain配置
在原有的安全链配置中,添加自定义的认证入口点:
@Bean SecurityFilterChain oauth2Security(HttpSecurity http, CustomAuthenticationEntryPoint customEntryPoint) throws Exception { http.cors(cors -> cors.configurationSource(corsConfigurationSource())) .csrf(csrf -> { csrf.csrfTokenRepository(csrfTokenRepository()); csrf.csrfTokenRequestHandler(csrfTokenRequestHandler()); }) .authorizeHttpRequests(authz -> authz .requestMatchers("/api/oauth2/login").permitAll() .anyRequest().authenticated()) .oauth2Login(Customizer.withDefaults()) // 配置自定义认证入口点 .exceptionHandling(ex -> ex.authenticationEntryPoint(customEntryPoint)); return http.build(); }
说明
- 请求判断逻辑可根据实际业务调整:比如你的API统一使用
/api/前缀(除登录端点),或者前端AJAX请求都会携带Accept: application/json头,都可以作为判断依据。 /api/oauth2/login已配置为允许匿名访问,不受认证入口点逻辑影响,仍会正常重定向到IDP完成登录并设置JSESSIONID。- 非API的浏览器请求(如地址栏直接输入URL)依旧会触发IDP重定向,不影响原有页面登录流程。
内容的提问来源于stack exchange,提问作者original_1887
相关产品推荐
相关产品推荐

