资讯详情

CORS与前后端联调-WebMvcConfig里的一行配置

📅 2026/9/24 3:52:17 | 华诺云谱 👁 阅读
CORS与前后端联调-WebMvcConfig里的一行配置
08-CORS与前后端联调-WebMvcConfig里的一行配置系列AI 伙伴AI-Partner——具身智能陪伴机器人 · 数据接口部署与二次开发篇08/12一、先搞懂为什么浏览器要多管闲事你本地把 AI 伙伴AI-Partner后端跑在 8080 端口又用前端页面开在 5500 端口调试结果浏览器控制台一抹红Access to XMLHttpRequest at http://localhost:8080/api/chat from origin http://localhost:5500 has been blocked by CORS policy很多新手的反应是接口坏了。其实接口好得很是浏览器在拦你。这就是同源策略Same-Origin Policy。同源的定义很严格协议、域名、端口三者全部相同才算同源。http://localhost:8080和http://localhost:5500域名相同但端口不同——不同源。浏览器规定不同源的情况下页面里的 JS可以发出请求但读不到响应更早一步某些请求连发都发不出去后面讲预检。这是浏览器的安全机制防止恶意网站拿着你的登录态去偷偷请求别的站点。关键词这是浏览器的行为。所以 curl、Postman、服务器之间的 HTTP 调用统统没有跨域问题——它们不经过浏览器。跨域只折磨浏览器里跑的页面。谁来解决服务端声明我允许谁来访问我这就是 CORS跨域资源共享。二、项目里的 CORS 配置逐行解读AI 伙伴AI-Partner的 CORS 配置在config/WebMvcConfig里短小精悍项目源码全文如下ConfigurationpublicclassWebMvcConfigimplementsWebMvcConfigurer{OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping(/api/**).allowedOriginPatterns(*).allowedMethods(GET,POST,PUT,DELETE,OPTIONS).allowedHeaders(*).maxAge(3600);}}逐项拆解配置项项目取值含义addMapping/api/**只对/api前缀的接口生效其他路径如根路径元信息接口不管allowedOriginPatterns*允许任意来源且是模式匹配式通配allowedMethodsGET/POST/PUT/DELETE/OPTIONS放行的 HTTP 方法白名单allowedHeaders*请求头全放行如 Content-Type、自定义 token 头maxAge3600预检结果缓存 1 小时见后文注意这个项目没有设置allowCredentials(true)所以*在这里不违法。但一旦要带 Cookie比如以后加会话鉴权情况就完全变了往下看。三、allowedOriginPatterns(““) 与 allowedOrigins(””)关键差异这两个方法长得像双胞胎行为却有本质区别也是 Spring 升级后最常见的报错来源方法语义与 allowCredentials(true) 组合allowedOrigins(*)响应头原样回Access-Control-Allow-Origin: *非法。浏览器规定带凭证时响应头必须是具体域名不允许*Spring 会直接抛异常allowedOriginPatterns(*)“任意来源都匹配”但响应头回显请求方的真实 Origin如http://localhost:5500合法。浏览器拿到具体域名允许带凭证换句话说allowedOrigins(*)是我对所有人说随便来allowedOriginPatterns(*)是谁来了我就对谁说你可以来——效果上都是全放行但后者能和 Cookie 组合使用。Spring Boot 2.4 之后如果你写allowedOrigins(*)又配了allowCredentials(true)启动就报When allowCredentials is true, allowedOrigins cannot contain the special value *。AI 伙伴AI-Partner选 patterns 的写法等于给未来的 Cookie 鉴权预留了兼容性——虽然当前项目没有拦截器和凭证校验这个选择依然是对的姿势。顺带把安全这盆冷水泼了全开 CORS 只适合开发联调。项目文档里也如实把收紧 CORS、加鉴权列进了生产建议。上生产前务必改白名单文末给写法。四、预检请求OPTIONS流程拆解为什么前端一个普通 POST会变成两个请求因为浏览器把跨域请求分两类简单请求方法为 GET/HEAD/POST且请求头都在安全列表内、Content-Type 仅限text/plain、multipart/form-data、application/x-www-form-urlencoded——直接发。非简单请求比如你的前端习惯性发Content-Type: application/json的 POSTAI 伙伴AI-Partner的/api/chat就是这种——浏览器会先发一个 OPTIONS 预检请求问服务器我能发吗得到许可再发真正的请求。完整时序演示浏览器 后端(8080) │ ── OPTIONS /api/chat ───────▶│ 预检不带业务数据 │ Origin: http://localhost:5500 │ Access-Control-Request-Method: POST │ ◀── 200 CORS 响应头 ───────│ │ Access-Control-Allow-Origin: http://localhost:5500 │ Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS │ Access-Control-Max-Age: 3600 │ ── POST /api/chat (JSON) ───▶│ 真实请求 │ ◀── {code:0,...} ──────────│两个实战要点maxAge(3600)的意义预检结果缓存 1 小时期间同一接口的跨域请求不再重复发 OPTIONS省一半往返。缓存期内你改了 CORS 配置却发现没生效先清缓存或换个无痕窗口再排查。OPTIONS 请求本身不经过你的业务代码所以不要在 Controller 里试图接住它Spring MVC 会自动应答。五、小程序与网页调试为什么会遇到跨域联调场景逐个说调试方式有跨域问题吗原因curl / Postman没有不经过浏览器本地网页file:// 或别的端口有经典跨域场景服务端配置 CORS 解决微信小程序开发者工具通常没有但体验版/真机可能遇到小程序用wx.request默认不检查 CORS但开发工具勾选不校验合法域名时走的是浏览器内核模拟部分场景仍会撞上Nginx 反代后的前端没有同域前端和/api都从同一个域名进出浏览器认为是同源这也是为什么很多团队最终选择 Nginx 把前端静态资源和后端接口收进同一个域名——跨域问题从物理上消失。而开发期最省事的方案就是像 AI 伙伴AI-Partner这样后端直接放开。另外提醒一句项目后端调用的视觉服务FastAPI自己也开了 CORS 全开allow_origins[*]如果你想让浏览器页面直连 8000 端口的视觉接口调试也不会被拦——但同理这是开发态配置。六、生产环境把*收紧成白名单示意生产环境的正确写法是把域名写死示意OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping(/api/**).allowedOriginPatterns(https://www.example.com,https://m.example.com).allowedMethods(GET,POST,PUT,DELETE).allowedHeaders(Content-Type,Authorization).maxAge(3600);}再讲究一点可以把域名列表放进配置文件或环境变量按spring.profiles区分 dev/prod——开发全开、生产白名单。记住三条红线生产不要allowedOriginPatterns(*)尤其加了 Cookie/Token 凭证之后allowedHeaders从*收敛到实际用到的头少暴露一个是一个若用了 Nginx 统一反代后端 CORS 甚至可以直接关掉让网关统一管。七、跨域排查表报错 → 原因 → 解决收好这张表联调遇到 CORS 报错按图索骥报错信息关键词原因解决No Access-Control-Allow-Origin header is present服务端没配 CORS或请求路径不在addMapping范围内确认配置覆盖了目标路径确认后端真的重启了has been blocked by CORS policy: Response to preflight request doesnt pass access control check预检OPTIONS被拒方法/头不在白名单或被拦截器挡了检查allowedMethods/allowedHeaders本项目暂无拦截器加了鉴权后要给 OPTIONS 放行The value of Access-Control-Allow-Origin header in the response must not be the wildcard * when the requests credentials mode is include前端带 Cookiecredentials: ‘include’服务端却回*用allowedOriginPatterns替代allowedOrigins并确认allowCredentials配置一致Method PUT is not allowed by Access-Control-Allow-Methods方法没进白名单白名单里补上该方法Request header field xxx is not allowed自定义请求头没放行allowedHeaders里加该头改了配置依旧报错预检缓存 1 小时未过期 / 浏览器缓存 / 配置没加载清浏览器缓存或换无痕窗口启动日志确认 WebMvcConfig 生效本地没问题上生产报跨域生产走了 Nginx/网关CORS 头被网关拦截或重复添加检查网关层是否也配了 CORS避免响应头重复八、收尾CORS 这件事本质是浏览器和服务端的一次握手确认浏览器问你允许我访问吗服务端答允许谁、用什么方法、带什么头、答复有效期多久。AI 伙伴AI-Partner用WebMvcConfig里不到 10 行的配置换来了前后端联调的丝滑开发期这是甜但它同时意味着任何网页都能调你的/api/**——生产期这就是裸奔。联调放开上线收紧这是纪律。配合下一阶段的鉴权和网关改造把门真正装上门锁。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。