前端安全之CORS跨域资源共享详解
字数 1725 2025-11-07 22:15:37
前端安全之CORS跨域资源共享详解
一、CORS是什么?
CORS(Cross-Origin Resource Sharing)是一种W3C标准,允许浏览器向跨域服务器发送XMLHttpRequest请求或Fetch请求,克服了同源策略的限制。它的核心是通过HTTP头部字段协商跨域权限。
二、为什么需要CORS?
- 同源策略限制:浏览器默认禁止跨域请求,但实际开发中前端经常需要访问不同域的API。
- 早期方案的缺陷:JSONP只支持GET请求,且缺乏错误处理;代理服务器会增加架构复杂度。
- CORS的优势:支持所有HTTP方法,安全性可控(服务端配置权限)。
三、CORS的两种请求类型
-
简单请求(Simple Request)
- 条件(同时满足):
- 方法为GET、POST、HEAD之一;
- 头部字段仅限允许的安全字段(如Accept、Content-Language、Content-Type等);
- Content-Type为
application/x-www-form-urlencoded、multipart/form-data或text/plain。
- 流程:
- 浏览器直接发送跨域请求,并在请求头自动添加
Origin: https://a.com; - 服务器返回响应头需包含
Access-Control-Allow-Origin: https://a.com(或*允许任意域); - 浏览器检查响应头,若匹配则允许获取数据,否则拦截响应。
- 浏览器直接发送跨域请求,并在请求头自动添加
- 条件(同时满足):
-
预检请求(Preflight Request)
- 触发条件(满足任一):
- 方法为PUT、DELETE等非简单方法;
- 包含自定义头部(如
Authorization); - Content-Type为
application/json。
- 流程:
- 浏览器先发送OPTIONS请求(预检请求),头部包含:
Origin: https://a.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: Content-Type,Authorization - 服务器响应预检请求,需返回以下头部:
Access-Control-Allow-Origin: https://a.com Access-Control-Allow-Methods: GET,POST,PUT Access-Control-Allow-Headers: Content-Type,Authorization Access-Control-Max-Age: 86400 // 缓存预检结果时间(秒) - 预检通过后,浏览器才发送真实请求,后续同简单请求流程。
- 浏览器先发送OPTIONS请求(预检请求),头部包含:
- 触发条件(满足任一):
四、关键HTTP头部字段详解
| 字段名 | 作用 | 示例 |
|---|---|---|
Origin |
声明请求的源 | Origin: https://a.com |
Access-Control-Allow-Origin |
服务器允许的源 | * 或 https://a.com |
Access-Control-Allow-Methods |
允许的HTTP方法 | GET,POST,PUT |
Access-Control-Allow-Headers |
允许的自定义头部 | Content-Type,Authorization |
Access-Control-Allow-Credentials |
是否允许发送Cookie | true(需配合前端设置withCredentials) |
Access-Control-Expose-Headers |
允许前端访问的响应头 | X-Custom-Header |
五、带凭证的请求
默认情况下,CORS请求不发送Cookie。若需携带凭证:
- 前端设置:
fetch(url, { credentials: 'include' // 或same-origin }); - 服务端响应头需满足:
Access-Control-Allow-Origin不能为*,必须指定具体域名;- 设置
Access-Control-Allow-Credentials: true。
六、常见问题与解决方案
- 预检请求失败:检查服务器是否正确响应OPTIONS请求,并返回允许的Methods和Headers。
- 响应被拦截:确保
Access-Control-Allow-Origin与Origin一致,且不带凭证时不能用通配符*。 - 缓存优化:通过
Access-Control-Max-Age减少预检请求频率。
七、实际配置示例(Node.js)
// 中间件设置CORS头
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'https://a.com');
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');
res.setHeader('Access-Control-Allow-Credentials', 'true');
// 预检请求直接返回200
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
八、总结
CORS通过服务端声明权限、浏览器验证的机制,在安全前提下实现了灵活跨域。开发时需注意区分简单/预检请求,正确设置头部字段,并谨慎处理带凭证的请求。