SpringBoot 3.1.2升级后,Angular+Nginx代理的CORS配置异常求助
SpringBoot 3.1.2升级后CORS 403问题解决指南
问题背景
将SpringBoot版本从2.x升级至3.1.2后,前端从https://www.example.com发起的请求到data.example.com时,返回403并提示“Invalid CORS request”。架构为:www.example.com通过CloudFront分发,data.example.com指向EC2实例,Nginx代理请求到SpringBoot应用,已排除身份认证问题,确认是CORS配置拦截。
核心原因
- Spring Security 6.x校验升级:SpringBoot3对应Spring Security6,CORS校验逻辑更严格,必须明确配置
AllowedOrigins,否则即使Nginx设置了CORS头,Spring Security仍会拦截请求。 - Nginx配置冗余冲突:同时在Nginx的server块和proxy请求中设置CORS头,导致请求头被重复传递给后端,干扰Spring的CORS校验。
解决步骤
1. 调整Spring Security CORS配置
生产环境必须明确配置允许的Origin,不能依赖Nginx,同时规范允许的请求头:
@Configuration @EnableWebSecurity @EnableMethodSecurity( securedEnabled = true, jsr250Enabled = true ) public class SecurityConfig { private final Environment environment; // 构造注入Environment public SecurityConfig(Environment environment) { this.environment = environment; } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); // 允许的请求方法 configuration.setAllowedMethods(List.of("POST","PUT","GET", "PATCH", "OPTIONS")); // 允许携带凭证 configuration.setAllowCredentials(true); // 区分环境配置允许的Origin if (Arrays.stream(environment.getActiveProfiles()).anyMatch("development"::equalsIgnoreCase)) { configuration.setAllowedOrigins(List.of("http://localhost:4200")); } else { // 生产环境建议从配置文件读取,比如@Value("${cors.allowed-origins}") configuration.setAllowedOrigins(List.of("https://www.example.com")); } // 明确允许的请求头,避免Spring拦截自定义头 configuration.setAllowedHeaders(List.of( "Authorization", "Accept", "Origin", "DNT", "X-CustomHeader", "Keep-Alive", "User-Agent", "X-Requested-With", "If-Modified-Since", "Cache-Control", "Content-Type", "Content-Range", "Range" )); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .cors(withDefaults()) // 保留原有角色/URL匹配配置... .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class) .build(); } }
2. 优化Nginx代理配置
移除冗余的CORS头设置,仅处理OPTIONS预检请求:
server { listen 443 ssl; server_name data.example.com; ssl_certificate /etc/ssl/certs/data.example.com.crt; ssl_certificate_key /etc/ssl/certs/data.example.com.key; ssl_protocols TLSv1.2 TLSv1.3; # 建议启用更安全的TLS版本 error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; location / { # 仅处理OPTIONS预检请求,返回必要的CORS响应头 if ($request_method = 'OPTIONS') { add_header Access-Control-Allow-Origin https://www.example.com always; add_header Access-Control-Allow-Credentials true always; add_header Access-Control-Allow-Headers Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range always; add_header Access-Control-Allow-Methods GET,POST,OPTIONS,PUT,DELETE,PATCH always; add_header Access-Control-Max-Age 1728000 always; add_header Content-Type 'text/plain charset=UTF-8' always; add_header Content-Length 0 always; return 204; } proxy_http_version 1.1; # 移除所有CORS相关的proxy_set_header,避免传递给后端干扰校验 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://127.0.0.1:8080; } location ~ /.well-known { allow all; } } server { listen 80; return 301 https://$host$request_uri; # 建议HTTP重定向到HTTPS,提升安全性 }
验证要点
- 重启SpringBoot应用和Nginx服务
- 用浏览器开发者工具检查请求头:
- 预检OPTIONS请求返回204
- 实际请求的响应头包含
Access-Control-Allow-Origin: https://www.example.com,且无重复头
- 确认请求不再返回403错误
内容的提问来源于stack exchange,提问作者DaFoot
相关产品推荐
相关产品推荐

