Web安全之同源策略的例外:CORS跨域资源共享详解
字数 914 2025-11-21 02:38:40
Web安全之同源策略的例外:CORS跨域资源共享详解
1. 问题背景与定义
当浏览器从https://a.com向https://b.com/api发起XMLHttpRequest请求时,控制台会出现错误:"Blocked by CORS policy"。这是由浏览器的同源策略引起的安全限制。CORS(跨域资源共享)是W3C标准,允许服务器声明哪些外部源有权访问资源,是当前最主流的跨域解决方案。
2. 核心概念解析
- 简单请求:满足以下所有条件的请求
- 方法为GET/HEAD/POST
- Content-Type为text/plain、multipart/form-data、application/x-www-form-urlencoded
- 无自定义头部(如Authorization)
- 预检请求:不满足简单请求条件的请求(如PUT/DELETE方法或自定义头部)
- 请求凭证:Cookies、HTTP认证等敏感信息
3. 简单请求的CORS流程
- 浏览器自动添加Origin头:
Origin: https://a.com - 服务器响应需包含:
Access-Control-Allow-Origin: https://a.com // 或通配符* Access-Control-Expose-Headers: X-Custom-Header // 允许前端访问的额外头部 - 浏览器检查响应头,若Origin值在Allow-Origin列表中,则解除拦截
4. 预检请求的完整流程
- 浏览器先发送OPTIONS请求(预检请求):
OPTIONS /api/data HTTP/1.1 Origin: https://a.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Custom-Header - 服务器响应预检:
Access-Control-Allow-Origin: https://a.com Access-Control-Allow-Methods: GET,PUT,POST Access-Control-Allow-Headers: X-Custom-Header Access-Control-Max-Age: 86400 // 预检结果缓存时间(秒) - 通过预检后,浏览器才发送实际请求
5. 带凭证的请求处理
当请求需要携带Cookies时:
- 前端设置:
xhr.withCredentials = true - 服务器响应需设置:
Access-Control-Allow-Origin: https://a.com // 不能为* Access-Control-Allow-Credentials: true
6. 服务端配置示例(Node.js/Express)
app.use((req, res, next) => {
const allowedOrigins = ['https://a.com', 'https://b.com'];
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization');
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Access-Control-Max-Age', '86400');
// 立即返回预检请求
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
7. 安全注意事项
- 避免使用
Access-Control-Allow-Origin: *与凭证混用 - 严格校验Origin头防止伪造(参考Origin头不可伪造特性)
- 敏感操作应额外实施CSRF保护
- 合理设置Max-Age平衡性能与安全
8. 常见问题排查
- 预检请求失败:检查Allow-Methods/Headers配置
- 凭证未被发送:确认withCredentials设置和服务器Allow-Credentials
- 缓存问题:预检结果缓存期间修改配置可能导致异常