You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 19:12:45