关键在于服务端预检响应必须明确允许自定义认证头,否则浏览器拦截请求;因非简单头触发options预检,服务端需用access-control-allow-headers原样列出authorization、x-request-id等头,大小写一致且不可遗漏。

处理复杂认证头部(如 Authorization、X-Auth-Token、X-Request-ID 等)的跨域请求,关键不在前端怎么发,而在于服务端是否在预检响应中明确“允许这些头”——否则浏览器连真实请求都不会发出。
为什么带自定义认证头会触发预检?
只要请求中包含非简单头(比如 Content-Type: application/json、Authorization: Bearer xxx 或任意 X- 开头的头),浏览器就判定为“复杂请求”,必须先发 OPTIONS 预检。预检请求里会带上:
Origin: https://app.company.comAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: Authorization, X-Request-ID, Content-Type
服务端必须在预检响应中,用 Access-Control-Allow-Headers 原样列出这些头,一个都不能少、大小写要一致,否则预检失败,后续请求被静默拦截。
服务端必须配置的对应响应头
微服务每个接口提供方(用户服务、订单服务等)都要独立设置,不能只靠网关兜底:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
Access-Control-Allow-Origin:必须写具体域名,例如
https://app.company.com;若需传 Cookie,绝不能用* -
Access-Control-Allow-Methods:至少包含实际用到的方法,如
GET, POST, PUT, OPTIONS;OPTIONS必须显式列出 -
Access-Control-Allow-Headers:把前端实际发送的所有自定义头都列全,例如
Authorization, X-Request-ID, Content-Type;Content-Type即使是application/json也得声明 -
Access-Control-Allow-Credentials:设为
true,且仅当前端fetch显式设置了credentials: 'include'时才需要
不同后端框架的典型写法
配置要精细,避免全局放行暴露内部接口:
-
Express.js:用
cors中间件按路径配置app.use('/api/users', cors({ origin: 'https://app.company.com', credentials: true, allowedHeaders: ['Authorization', 'X-Request-ID', 'Content-Type'] })) -
Spring Boot:在 Controller 方法上加注解
@CrossOrigin(origins = "https://app.company.com", allowCredentials = "true", allowedHeaders = {"Authorization", "X-Request-ID"}) -
Next.js API Route:结合
cors包和中间件
在pages/api/xxx.ts中调用runCorsMiddleware(req, res),并确保credentials: true和allowedHeaders同步配置
前端 fetch 的配合要点
前端代码本身很轻量,但两个细节不能错:
- 发送请求时,正常带认证头,例如:
headers: { 'Authorization': 'Bearer abc123', 'X-Request-ID': 'req-789' } - 如果需要携带 Cookie 或认证凭证,必须加:
credentials: 'include'(注意不是'same-origin'或'omit')
不需要手动发 OPTIONS,也不用判断是否跨域——浏览器全自动处理,你只管写业务逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










