Web 安全

CORS (跨源资源共享)

约 4 分钟阅读

什么是 CORS (跨源资源共享)

CORS (Cross-Origin Resource Sharing) 是一种基于 HTTP 头的机制,用于安全地放宽浏览器的同源策略,实现不同源之间的资源共享。源由协议 (http/https)、主机名和端口号三个要素的组合定义。

同源策略是浏览器的安全机制,限制从一个源加载的脚本访问另一个源的资源。如果没有这个限制,恶意网站就可以通过用户的浏览器调用用户已登录的银行网站的 API。

然而,在现代 Web 应用中,前端和后端 API 运行在不同域名上是很常见的。CORS 通过服务器在 HTTP 响应头中明确声明「允许哪些源的访问」,安全地实现必要的跨源通信。

CORS 的工作机制

CORS 根据请求类型以两种方式工作。

简单请求 (Simple Request)

使用 GET、HEAD 或 POST (限于特定 Content-Type) 且不包含自定义头的请求被视为「简单请求」。浏览器直接发送请求,并检查响应中的 Access-Control-Allow-Origin 头。如果源被允许,则将响应传递给 JavaScript;否则阻止。

预检请求 (Preflight Request)

对于不满足简单请求条件的请求 (如 PUT、DELETE 或包含自定义头的请求),浏览器在实际请求之前使用 OPTIONS 方法发送「预检请求」。服务器通过以下头响应允许条件。

  • Access-Control-Allow-Origin:允许的源
  • Access-Control-Allow-Methods:允许的 HTTP 方法
  • Access-Control-Allow-Headers:允许的请求头
  • Access-Control-Max-Age:预检结果的缓存时间 (秒)

如果预检响应满足允许条件,浏览器才发送实际请求。

携带凭据的请求

包含 Cookie 或认证头的跨源请求需要 Access-Control-Allow-Credentials: true。此时,Access-Control-Allow-Origin 不能使用通配符 (*),必须指定具体的源。

常见配置错误与安全风险

CORS 配置错误会使同源策略的保护失效,造成严重的安全风险。

  • 随意使用 Access-Control-Allow-Origin: *:允许所有源意味着任何网站都可以访问 API。除公开 API 外不应使用。处理认证信息的 API 绝对不能使用
  • 未经验证直接反映 Origin 头:将请求的 Origin 头值直接反映到 Access-Control-Allow-Origin 中,实质上等同于通配符。应通过白名单验证
  • 允许 null 源:允许 Access-Control-Allow-Origin: null 会使沙箱化的 iframe 和本地文件可以访问,可能被攻击利用
  • 过于宽松的子域匹配:使用 *.example.com 这样的模式匹配时,如果攻击者能够接管子域,就可以利用 CORS

CORS 配置错误与 XSSCSRF 结合时,可能扩大危害。

安全 CORS 配置的最佳实践

安全配置 CORS 的指南。

  • 通过白名单管理允许的源:在环境变量或配置文件中维护允许源列表,与请求的 Origin 头进行精确匹配验证
  • 仅允许最少必要的方法和头:在 Access-Control-Allow-MethodsAccess-Control-Allow-Headers 中只列出实际使用的内容
  • 利用预检缓存:适当设置 Access-Control-Max-Age,减少预检请求频率,提升性能
  • 谨慎处理携带凭据的请求:设置 Access-Control-Allow-Credentials: true 时,严格限制允许的源
  • CSP安全头配合使用:将 CORS 与其他安全头结合,构建纵深防御
  • HTTPS 为前提:不在允许列表中包含 HTTP 源。防止通过中间人攻击伪造源

CORS 是浏览器端的控制,不适用于服务器间通信或命令行工具的请求。不要仅依赖 CORS,务必实现服务器端的认证和授权。

常见误解

CORS 是保护服务器的安全功能
CORS 是浏览器端的控制,不直接保护服务器。curl 或服务器间通信不受 CORS 限制。CORS 是保护浏览器用户的机制,与服务器端的认证和授权处于不同层面。
出现 CORS 错误用通配符 (*) 解决就好
通配符允许所有源的访问,安全风险很高。携带凭据的请求不能使用通配符。正确的做法是仅将必要的源添加到白名单中。
分享

相关术语