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

页面刷新时JSESSIONID Cookie传递异常的修复方案

Spring Boot 3.2 OAuth2 刷新页面触发401授权错误问题

问题背景

按Spring Boot OAuth2官方文档,OAuth2授权后生成的JSESSIONID本应满足基础安全需求,但按下F5刷新页面后,会话Cookie被删除,首次请求触发授权错误,返回401状态码。当前异常处理配置如下:

http.exceptionHandling(exHandler ->
        exHandler.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)));

客户端(Angular 17)配置

客户端运行在localhost:4200,配置了携带凭证的请求拦截器:

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const clonedRequest = req.clone( { withCredentials: true } );
  return next(clonedRequest);
};

同时配置了错误拦截器,收到401时跳转至登录页:

export const errorInterceptor: HttpInterceptorFn = (req, next) => {
  const router = inject(Router);
  return next(req).pipe(catchError(err => {
    if (err.status === 401) {
      router.navigate(['/']);
    }
    return throwError(err);
  }));
};

错误现象

  • 获取JSESSIONID后Angular控制台无报错,但刷新页面后出现以下错误日志:
status: 401,
  statusText: 'Unknown Error',
  url: 'http://localhost:8080/api...',
  ok: false,
  name: 'HttpErrorResponse',
  message: 'Http failure response for http://localhost:8080/api...: 401 ',
  error: null
  • 同一请求最终会返回正常结果,浏览器中所有请求状态显示为200,但控制台先收到401错误,再得到正常响应
  • 刷新页面时,登录页会瞬间闪显

Spring Boot 3.2 安全配置代码

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Autowired
    private OAuth2LoginSuccessHandler oauth2LoginSuccessHandler;

    @Value("${spring.security.cors.allowed-origin}")
    private String allowedOrigin;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http.csrf(AbstractHttpConfigurer::disable);

        http.cors(cors -> cors.configurationSource(request -> {
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.addAllowedOrigin(allowedOrigin);
            corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
            corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
            corsConfiguration.setAllowCredentials(true);
            return corsConfiguration;
        }));

        http.authorizeHttpRequests(authorizeHttpRequests ->
                authorizeHttpRequests
                        .requestMatchers(HttpMethod.OPTIONS).permitAll() // CORS 预检请求放行
                        .anyRequest().authenticated()
        );

        http.oauth2Login(oauth2Login -> {
                    oauth2Login.successHandler(oauth2LoginSuccessHandler);
                    oauth2Login.failureHandler((request, response, exception) -> {
                        request.getSession().setAttribute("error.message", exception.getMessage());
                        response.setStatus(HttpStatus.UNAUTHORIZED.value());
                    });
                }
        );

        http.exceptionHandling(exHandler ->
                exHandler.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)));

        http.httpBasic(AbstractHttpConfigurer::disable);
        return http.build();
    }

}

解决方案建议

  • 调整Cookie的SameSite属性:默认JSESSIONID的SameSite属性为Lax,跨域场景下刷新页面可能无法携带。需设置为None,并开启Secure(生产环境需HTTPS),在Spring中新增配置:
    @Bean
    public ServletContextInitializer servletContextInitializer() {
        return servletContext -> {
            servletContext.getSessionCookieConfig().setSameSite("None");
            servletContext.getSessionCookieConfig().setSecure(true); // 本地开发可根据实际情况关闭
        };
    }
    
  • 替换认证入口处理器:当前HttpStatusEntryPoint直接返回401,未触发OAuth2授权流程。替换为OAuth2AuthenticationEntryPoint,让未认证请求自动触发登录:
    http.exceptionHandling(exHandler ->
            exHandler.authenticationEntryPoint(new OAuth2AuthenticationEntryPoint()));
    
  • 优化Angular错误拦截逻辑:排除预检请求,避免误跳转登录页:
    export const errorInterceptor: HttpInterceptorFn = (req, next) => {
      const router = inject(Router);
      return next(req).pipe(catchError(err => {
        if (err.status === 401 && req.method !== 'OPTIONS' && err.error !== null) {
          router.navigate(['/']);
        }
        return throwError(err);
      }));
    };
    
  • 验证会话持久化配置:检查Spring Boot会话超时时间、是否开启会话持久化(如Redis),避免刷新页面时会话丢失。

内容的提问来源于stack exchange,提问作者shmel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 23:10:21