Spring Boot 3中Spring Security的CORS预检请求401错误求助
解决Spring Boot 3 + Spring Security 预检OPTIONS请求401问题
核心原因
升级到Spring Boot 3后,JWT请求过滤器会拦截所有请求(包括OPTIONS预检请求),但OPTIONS请求不会携带Authorization令牌,导致被判定为未认证返回401;同时你的CORS配置存在冲突(通配符Origin与允许凭证不能共存),也会影响预检请求的正常处理。
解决方案步骤
1. 修改JWT过滤器,跳过OPTIONS请求
在你的JwtRequestFilter的doFilterInternal方法开头添加判断,直接放行OPTIONS请求:
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 直接放行OPTIONS预检请求 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); filterChain.doFilter(request, response); return; } // 原有JWT令牌验证逻辑... }
2. 调整SecurityFilterChain配置,明确放行OPTIONS请求
在authorizeHttpRequests中添加对OPTIONS请求的全局放行,确保Spring Security不会拦截它们:
@Bean public SecurityFilterChain configure(HttpSecurity httpSecurity) throws Exception { httpSecurity .cors(c -> c.configurationSource(corsConfigurationSource())) .csrf(c -> c.disable()) .authorizeHttpRequests(requests -> requests // 全局放行所有OPTIONS请求 .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .requestMatchers( AntPathRequestMatcher.antMatcher("/comments/**"), AntPathRequestMatcher.antMatcher("/requests/admin/**") ).authenticated() .anyRequest().permitAll()) .authenticationProvider(authenticationProvider()) .exceptionHandling(r -> r.authenticationEntryPoint(jwtAuthenticationEntryPoint)) .sessionManagement(r -> r.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); return httpSecurity.build(); }
3. 修复CORS配置的冲突问题
浏览器不允许**带凭证(AllowCredentials=true)**的CORS请求使用通配符*作为AllowedOrigins,必须指定具体的前端域名。修改你的CORS配置:
@Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration corsConfig = new CorsConfiguration(); corsConfig.setAllowCredentials(true); // 替换为你的实际前端域名,多个可添加多个元素 corsConfig.setAllowedOrigins(Arrays.asList("http://localhost:3000", "https://your-production-frontend.com")); // 明确允许的HTTP方法 corsConfig.setAllowedMethods(Arrays.asList("GET", "PATCH", "POST", "OPTIONS", "PUT", "DELETE")); // 允许的请求头,包含Authorization(JWT令牌需要) corsConfig.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "X-Requested-With")); // 暴露前端需要读取的响应头(比如返回的JWT令牌) corsConfig.setExposedHeaders(Arrays.asList("Authorization")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfig); return source; }
验证
重启应用后,测试OPTIONS预检请求,应该返回200状态码,后续的实际请求也能正常通过认证。
内容的提问来源于stack exchange,提问作者Jurn
相关产品推荐
相关产品推荐

