当前位置: 首页 > news >正文

CORS配置文件

可以。结合浏览器侧的 CORS 标准说明和 Spring 官方文档,常见配置项基本可以分成两层来看:

一层是HTTP/CORS 规则本身,也就是浏览器认哪些响应头。另一层是Spring 里的配置 API,比如allowedOriginsallowedMethods,它们本质上是在生成这些 CORS 响应头。CORS 是一种基于 HTTP 头的机制;当请求属于“非简单请求”时,浏览器会先发一个OPTIONS预检请求,确认服务端是否允许真正的跨域请求。(MDN文档)

你现在最关心的,可以按下面这些项理解。

1. 允许哪些来源:allowedOrigins/Access-Control-Allow-Origin

这是最核心的一项,表示哪些前端来源可以访问后端资源。浏览器看的是响应头Access-Control-Allow-Origin。它可以是某个明确的源,例如http://localhost:5173,也可以是*表示任意源。MDN 还特别提醒:当返回的是具体 origin 而不是*时,响应通常应同时带上Vary: Origin,这样缓存才不会把某个来源的结果错误复用给别的来源。(MDN文档)

在 Spring 里,对应的是allowedOrigins(...);Spring 的CorsRegistrationCorsConfiguration都把它定义为“允许浏览器发起跨域请求的来源列表”。(Home)

实际作用很好理解:

  • 只允许你的前端地址访问后端
  • 防止随便一个别的站点也能直接拿到接口响应

2. 允许哪些 HTTP 方法:allowedMethods/Access-Control-Allow-Methods

这项表示跨域请求允许使用哪些方法,例如GETPOSTPUTDELETEOPTIONS。对预检请求来说,浏览器会先问:“我等下想用某种方法发请求,行不行?” 服务端就要通过Access-Control-Allow-Methods告诉浏览器哪些方法被允许。MDN 里明确列出,如果预检阶段在这个头里找不到目标方法,浏览器就会判定失败。(MDN文档)

所以你前面遇到的情况就很典型:配置里没放OPTIONS,预检直接被拦,浏览器报 CORS 错。Spring 文档也说明它支持配置允许的方法列表。(Home)


3. 允许哪些请求头:allowedHeaders/Access-Control-Allow-Headers

这项表示前端真实请求里允许带哪些自定义请求头。常见的就是:

  • Authorization
  • Content-Type
  • X-Requested-With

对于预检请求,浏览器会把自己准备发送的头放在Access-Control-Request-Headers中;如果服务端没有在Access-Control-Allow-Headers里允许这些头,浏览器就不会继续发真实请求。MDN 明确说了:当预检请求带有Access-Control-Request-Headers时,这个响应头是必需的。(MDN文档)

这也是很多“登录成功,但带 token 的接口失败”的另一常见根因:不是方法没放行,而是Authorization头没放行。Spring 中对应allowedHeaders(...)。(Home)


4. 是否允许携带凭证:allowCredentials/Access-Control-Allow-Credentials

这项表示浏览器是否可以在跨域请求中携带凭证,例如:

  • Cookie
  • HTTP 认证信息
  • 某些带凭据的请求上下文

MDN 说明得很清楚:Access-Control-Allow-Credentials的有效值只有true;如果需要凭证但服务端没返回这个头,浏览器会报网络错误。它还强调了一个很重要的限制:当允许凭证时,Access-Control-Allow-Origin不能用*。(MDN文档)

在 Spring 里,对应allowCredentials(...)。这项经常用于:

  • 前后端分离但仍用 Cookie 会话
  • 需要跨域发送认证信息的场景

如果你们前端是用Authorization: Bearer xxx,这通常更多和allowedHeaders、预检放行相关;如果是 Cookie 登录态,则allowCredentials(true)更关键。Spring 文档也提到,像allowCredentialsmaxAge这类单值属性,局部配置会覆盖全局配置。(Home)


5. 预检结果缓存多久:maxAge/Access-Control-Max-Age

这项表示浏览器可以把预检结果缓存多长时间,单位通常是秒。意思是:在缓存有效期内,浏览器不必每次都先发一遍OPTIONS,性能会更好。Spring 官方文档把它作为 CORS 常见配置项之一;CorsConfiguration也明确提供了maxAge相关设置。(Home)

它的作用主要是减少预检开销,尤其是接口调用频繁的时候。


6. 允许前端读取哪些响应头:exposedHeaders/Access-Control-Expose-Headers

默认情况下,浏览器并不会把所有响应头都暴露给前端 JS。

如果你希望前端通过fetchaxios读取某些响应头,比如:

  • Content-Disposition
  • X-Trace-Id
  • X-Total-Count

就要通过Access-Control-Expose-Headers显式暴露。Spring 里对应exposedHeaders(...),Spring 官方把它列为标准 CORS 配置项之一。(Home)

它的作用是:后端虽然返回了头,但前端 JS 默认未必能读到;暴露后才能读。


7. 允许的来源模式:allowedOriginPatterns

这是 Spring 里的一个增强项,不是浏览器 CORS 头的名字,而是 Spring 为了方便配置提供的模式匹配能力。CorsRegistration官方 API 里明确说明了allowedOriginPatterns(...),并指出如果同时设置了allowedOriginPatterns,它会优先生效。(Home)

它适合这种场景:

  • 本地开发多个端口
  • 一批子域名要放行
  • 不想一个个把 origin 写死

allowedOrigins的区别是:

  • allowedOrigins更适合精确列举
  • allowedOriginPatterns更适合模式匹配

8. 全局配置与局部配置

Spring 官方文档说明,CORS 可以做全局配置,也可以做局部配置;一般规则是多数属性会做叠加,但像allowCredentialsmaxAge这类单值属性,局部会覆盖全局。(Home)

这在实际项目里很重要,因为经常会出现:

  • 全局允许一组前端域名
  • 某个接口单独再收紧或放宽规则

9. 一个常见误区:只配 methods,不配 headers

你前面的案例就是最容易踩坑的组合之一。很多人会写:

.allowedMethods("GET","POST","PUT","DELETE")

但如果真实请求带:

  • Authorization
  • 或特殊Content-Type

那只配 methods 还不够,还要确保:

  • OPTIONS放行
  • AuthorizationallowedHeaders里被允许
  • 如果走 Cookie,会话类场景还要考虑allowCredentials。这些都是浏览器 CORS 机制和 Spring 官方配置模型共同要求的。(MDN文档)

一个实战层面的理解框架

可以把常见配置项记成这 6 个问题:

  1. 谁能来?

    allowedOrigins/allowedOriginPatterns

  2. 能用什么方法来?

    allowedMethods

  3. 请求里能带什么头?

    allowedHeaders

  4. 能不能带凭证?

    allowCredentials

  5. 前端能读哪些响应头?

    exposedHeaders

  6. 预检结果缓存多久?

    maxAge


一个常见的 Spring 配置示意

只作为理解示意:

registry.addMapping("/**").allowedOrigins("http://localhost:5173").allowedMethods("GET","POST","PUT","DELETE","OPTIONS").allowedHeaders("Authorization","Content-Type").exposedHeaders("Content-Disposition").allowCredentials(true).maxAge(3600);

这段的语义就是:

  • 允许http://localhost:5173调你
  • 允许这些方法,包括预检用的OPTIONS
  • 允许前端带AuthorizationContent-Type
  • 允许前端读取Content-Disposition
  • 允许携带凭证
  • 预检结果缓存 1 小时
http://www.jsqmd.com/news/675164/

相关文章:

  • 计算机毕业设计:Python棉花种植产量与市场价格监测系统 Django框架 ARIMA算法 数据分析 可视化 爬虫 大数据 大模型(建议收藏)✅
  • 口碑好的不锈钢彩涂板企业
  • 如何正确对对象键名进行字母序排序并存入数组
  • CSS如何实现模块化的颜色主题_通过CSS变量集中定义色板.txt
  • 零基础入门Coze-Loop:JavaScript代码优化保姆级教程
  • <numeric>
  • Z-Image开源大模型调试工具:LM系列权重一键注入+生成结果自动标注
  • 告别混乱!在uni-app中优雅管理推送消息与角标:一个封装好的Push工具类详解
  • BitNet b1.58-2B-4T-GGUF快速上手:WebUI界面操作+System Prompt调优指南
  • 别再死磕90%!手把手教你用STL软件测试库搞定ISO 26262 ASIL B认证
  • 计算机毕业设计:Python农产品电商数据挖掘与推荐系统 Flask框架 矩阵分解 数据分析 可视化 协同过滤推荐算法 深度学习(建议收藏)✅
  • 郑州城市职业学院:作息安排与住宿生活全知道
  • nli-MiniLM2-L6-H768惊艳效果:支持‘跨语言标签’(English label + 中文文本)混合推理
  • Beaver Notes(海狸笔记)v4.4.0 中文版 ,开源免费、本地存储、零追踪的笔记软件
  • 冰雪传奇三职业深度解析!官方认证下支持安卓、iOS、PC 三端互通
  • Dify快速集成Slack通知、企微审批、AWS Lambda:3步自动化上线,附可运行YAML模板
  • Asian Beauty Z-Image Turbo 技术解析:透过LSTM理解序列生成在扩散模型中的角色
  • Django 表单实战:从 0 到 1 实现用户注册表单(Form/ModelForm 详解)
  • 别再傻傻用typeid判断类型了!C++运行时类型识别(RTTI)的完整指南与实战避坑
  • Typora Markdown写作助手:集成GLM-4.7-Flash实现智能排版
  • Phi-3.5-mini-instruct多场景落地:教育机构AI助教系统建设实践
  • 预算为0也能上系统?揭秘私藏的5个“零成本”数字化神器
  • real-anime-z企业应用:品牌IP延展——从LOGO生成配套动漫风格VI素材
  • 《不花一分钱,让你的QClaw在Mac上跑得比云端还快》
  • Qianfan-OCR惊艳效果:手写体混合印刷体合同中签名区域+条款文本分离展示
  • 【限时首发|Loom安全迁移黄金72小时】:20年JVM专家手把手带你完成存量Spring Boot项目响应式重构+全链路安全加固(含自动化检测脚本)
  • 别再拍脑袋估工时了!用FPA功能点分析法,像东北电网那样精准评估软件开发工作量
  • real-anime-z新手误区纠正:不是步数越高越好,12步+LoRA强度1.0更高效
  • 易基因: Nat Plants:南科大朱健康/华中农大赵伦团队aChIP-seq+WGBS表观多组学揭示ROS1调控DNA去甲基化新机制
  • Phi-3.5-mini-instruct开源可部署:提供完整Dockerfile与K8s Helm Chart模板