应使用WebMvcConfigurer做全局CORS配置,避免仅用@CrossOrigin注解;需明确设置allowedOrigins为具体域名(禁用"*")、允许凭据时设allowCredentials=true、包含OPTIONS方法、显式配置exposedHeaders和maxAge,Spring Boot 3.x需注意allowedOrigins默认为null及布尔值要求。

全局配置用 WebMvcConfigurer,别只加 @CrossOrigin 注解
单个接口上加 @CrossOrigin 能跑通,但项目一多就失控:重复配、漏配、前端换域名后全挂。真正稳的方案是统一在 WebMvcConfigurer 里做全局规则,把预检请求(OPTIONS)、凭证支持、允许头这些一次写对。
-
@CrossOrigin只作用于当前方法或类,不接管 OPTIONS 预检逻辑,浏览器发预检时可能直接 403 - 全局配置能控制
allowedOrigins的动态性,比如本地开发用"http://localhost:3000",上线切到正式域名,不用改每个接口 - 如果前端带
withCredentials: true,allowedOrigins不能写"*",必须明确指定,否则浏览器拒绝响应
addCorsMappings 里怎么设 origin 才不踩坑
最常犯的错是把 allowedOrigins 写成 "*" 后发现带 cookie 的请求失败,或者线上环境被恶意站点调用接口。根源在于 CORS 对凭据和通配符的互斥限制。
- 需要携带 cookie 或 Authorization header 时,
allowedOrigins必须是具体域名列表,例如Arrays.asList("https://a.com", "https://b.net") - 开发阶段想兼容所有前端端口,可以用
"http://localhost:*",但 Spring Boot 2.4+ 要求显式启用 pattern 支持:corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:*")),且需确保allowCredentials设为true - 生产环境禁用
"*",哪怕只是临时调试——它会绕过浏览器对凭据的保护机制
@CrossOrigin 和 WebMvcConfigurer 冲突时谁生效
两者共存时,Spring Boot 会合并配置,但优先级有隐含规则:局部注解覆盖全局默认值,但不会覆盖全局显式禁止的项(比如全局设了 maxAge = 300,局部没设,就用 300;局部设了 maxAge = 600,就用 600)。
- 全局配置里设
allowedHeaders = ["*"],接口上再用@CrossOrigin(allowedHeaders = "X-Req-ID"),最终允许的是["X-Req-ID"],不是合并结果 - 如果全局禁用了
allowCredentials(设为false),接口上加@CrossOrigin(..., allowCredentials = "true")会被忽略——Spring 认为这是不安全的降级 - 预检请求(OPTIONS)永远走全局配置路径,
@CrossOrigin对它无效,所以务必在addCorsMappings中确认allowedMethods包含"OPTIONS"
Spring Boot 3.x 升级后 CorsConfiguration 的变化
从 2.7 迁移到 3.x 时,CorsConfiguration 默认行为收紧:allowedOrigins 默认为 null(即不允许任何源),而不是以前的空集合;allowCredentials 默认为 false,且不再接受字符串 "true",必须用布尔值。
- 升级后没显式配置
allowedOrigins,所有跨域请求都会 403,连本地开发都挂——这不是 bug,是安全加固 - 旧代码里写
corsConfiguration.setAllowCredentials("true")会编译失败,要改成corsConfiguration.setAllowCredentials(true) -
allowedOrigins若需支持多个域名,必须用Arrays.asList(...),不能传null或留空,否则 Spring 直接拒绝匹配
maxAge)和暴露头(exposedHeaders)。比如前端要读取 X-Total-Count,光允许跨域不够,还得在配置里加上 exposedHeaders = ["X-Total-Count"],否则 JavaScript 拿不到这个字段。










