CORS
本文约需 2 分钟阅读
CORS (Cross-Origin Resource Sharing,跨源资源共享) 是浏览器向不同源 (域名、端口、协议的组合) 的服务器发送请求时的访问控制机制。它于 2014 年由 W3C 发布为推荐标准,目前所有主流浏览器都已实现。如今,Web 应用将前端和后端运行在不同域名上的架构已经普及,正确理解和配置 CORS 已成为 Web 开发者的必备技能。它也是与 CSRF 和 XSS 密切相关的安全机制。
与同源策略 (SOP) 的关系
要理解 CORS,首先需要了解同源策略 (Same-Origin Policy)。SOP 是 1995 年在 Netscape Navigator 2.0 中引入的浏览器安全模型,其约束是「从某个源加载的脚本无法访问另一个源的资源」。
如果没有 SOP,恶意网站调用银行网站的 API 获取用户账户信息这类攻击就很容易得逞。CORS 是用于安全地放宽这一 SOP 约束的机制。通过服务器明确声明「允许来自此源的请求」,使合法的跨源通信成为可能。
预检请求 (OPTIONS) 的机制
在发送满足特定条件的跨源请求之前,浏览器会使用 OPTIONS 方法发送「预检请求」。这是向服务器事先确认「是否接受此请求?」的机制。
触发预检的条件包括使用 PUT / DELETE / PATCH 方法、Content-Type: application/json 等自定义头的发送、认证信息 (Cookie) 的发送等。如果 GET 请求没有自定义头,则被视为「简单请求」,预检会被省略。
主要的 CORS 响应头
| 头 | 作用 | 注意事项 |
|---|---|---|
| Access-Control-Allow-Origin | 指定允许的源 | 通配符 (*) 不可与带认证信息的请求并用 |
| Access-Control-Allow-Methods | 列举允许的 HTTP 方法 | 在预检响应中返回 |
| Access-Control-Allow-Headers | 列举允许的请求头 | 明确列出 Authorization 等自定义头 |
| Access-Control-Allow-Credentials | 允许发送 Cookie 等认证信息 | 为 true 时,Allow-Origin 不能使用 * |
| Access-Control-Max-Age | 预检结果的缓存秒数 | 过长会导致配置变更的生效延迟 |
常见的错误配置及其风险
允许所有源的设置。对公开 API 是合适的,但若配置在需要认证的 API 上,恶意网站就能获取用户数据。由于无法与 Credentials 并用,在使用 Cookie 认证的 API 上无法生效。
将请求的 Origin 头的值原样返回到 Allow-Origin 的实现。实质上等同于允许所有源,但由于可以与 Credentials: true 并用,比 * 更危险。
设置 Access-Control-Allow-Origin: null 会允许来自沙箱 iframe 或本地文件的请求。会被攻击者用于从 iframe 内调用 API 的攻击。
CORS 与 CSRF 的关系
CORS 和 CSRF 常被混淆,但二者防御的对象不同。CORS 是浏览器控制响应读取的机制,对请求的发送本身 (在简单请求的情况下) 并不会拦截。也就是说,即使正确配置了 CORS,也可能无法阻止 CSRF 攻击发出的请求。CSRF 防护需要令牌方式或 SameSite Cookie 属性等另外的防御层。与 CSP 和 SSL/TLS 相结合的多层防御很重要。
在使用 API 密钥 的服务中,CORS 的配置错误有时也会导致 API 密钥泄露。也请一并参阅 浏览器扩展程序的安全、API 密钥管理的最佳实践、初创公司的安全检查清单。Web API 安全相关书籍 (Amazon)推荐用来学习实现模式。
这篇文章对您有帮助吗?