CORS 这个东西,平时不遇到的时候你根本想不起它。一遇到就是浏览器控制台满屏红字。
我有 6 个微服务,每个都有自己的前端。一天之内,6 个前端全报 CORS 错误。中午没吃饭,晚上十点才搞定。今天复盘一下:到底错在哪、怎么一次性解决。
什么是 CORS(30 秒版本)
浏览器有个安全策略:一个域名的页面不能随便调另一个域名的 API。
比如console.wuxiannet.com的前端调auth.wuxiannet.com的登录接口,浏览器会先发一个 OPTIONS 预检请求,问服务器「你允许这个域名调你吗?」。服务器在响应头里返回Access-Control-Allow-Origin,浏览器才放行真正的请求。
这个头写错了,或者没写,就报 CORS 错误。
我踩的三个坑
坑①:Nginx 和 Spring 各加了一次 CORS 头
我第一次配的时候,Nginx 里写了:
add_header Access-Control-Allow-Origin *;Spring Boot 里也配了 CorsConfiguration。结果响应头里出现了两个Access-Control-Allow-Origin——浏览器看到重复的 CORS 头直接拒绝。
解决:CORS 只在一层配。要么 Nginx,要么 Spring Boot。我的选择是 Spring Boot 统一配,Nginx 不碰 CORS。
坑②:*和Credentials: true不兼容
Spring Boot 里我一开始写了:
setAllowedOrigins(["*"])allowCredentials(true)这两个写到一起,浏览器会报错:「当 credentials 为 true 时,Access-Control-Allow-Origin 不能是 *」。因为*意味着「允许所有域名」,但如果带了 cookie,浏览器需要知道具体是哪个域名。
解决:用setAllowedOriginPatterns代替setAllowedOrigins。*在 pattern 模式下可以跟 credentials 共存。
坑③:OPTIONS 预检请求没处理
有的请求浏览器会先发 OPTIONS,如果不返回正确的头,真正的请求根本发不出去。我一开始漏了 OPTIONS 的处理。
Spring Boot 的CorsConfigurationSource配好了会自动处理,不需要额外写 OPTIONS 路由。但如果用了自定义 Filter,要确保 Filter 不拦截 OPTIONS。
最终的统一 CORS 配置
@BeanpublicCorsConfigurationSourcecorsConfigurationSource(){CorsConfigurationconfig=newCorsConfiguration();config.setAllowedOriginPatterns(List.of("http://localhost:*","http://127.0.0.1:*","https://*.wuxiannet.com"));config.setAllowCredentials(true);config.setAllowedMethods(List.of("*"));config.setAllowedHeaders(List.of("*"));UrlBasedCorsConfigurationSourcesource=newUrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**",config);returnsource;}这段代码我复制到了 6 个服务里。一模一样,不差一个字符。
回头看看
CORS 的问题从来不是「不会配」,而是「多个地方各配各的」,相互打架。
经验就一条:CORS 只在一个地方配。我选 Spring Boot,因为跟代码在一起,改起来方便。Nginx 只管反向代理和 SSL,别管 CORS。
关于作者:无羡,独立开发者,全栈工程师,专注 AI 应用与微服务架构。
📌 分类:技术复盘
🔗 个人博客 — 更多技术文章
✨ 开发者福利整理 — 云服务资源汇总
📂 软件工坊 — 我的技术分享
🌐 个人门户 — 独立开发作品全集