HTTP CORS
Cross-Origin Resource Sharing,跨域资源共享
基于同源策略,浏览器会限制由脚本发起的 cross-origin HTTP request。比如 XMLHttpRequest 和 Fetch API 都遵循 same-origin 策略,这意味着使用这些 API 的 Web 应用程序只能从 same-origin 请求资源,除非来自其它 origin 的 HTTP response 包含正确的 CORS header。
CORS 是一种基于 HTTP header 的机制,它能够让 Web server 自主地选择允许访问其资源的 cross-origin,浏览器以此为依据决定是否阻止前端 JavaScript 代码访问 cross-origin request 的 response。CORS 比简单地允许所有 cross-origin 请求更安全,比纯粹的同源请求有更多的自由度和功能。
Cross-Origin Sharing Standard 为以下场景启用 cross-origin HTTP request:
JavaScript
XMLHttpRequest API 的调用
Fetch API 的调用
CSS
@font-face
使用 Web Fontshape-outside: url()
Canvas
用 drawImage()
绘制图像和视频
WebGL
texture
工作原理
CORS 标准的工作原理是添加新的 HTTP header,让服务器描述 Web 浏览器可以允许哪些 cross-origin 能访问自己。
CORS 还依赖于一种机制:预检请求。对于简单的 GET 请求,不会进行预检。对于可能对服务器数据产生副作用的 HTTP 请求方法,该规范要求浏览器预检请求。浏览器首先向 cross-origin 的资源发送一个 HTTP OPTIONS 请求,从服务器获得请求支持的方法,以检查服务器是否允许实际请求,在服务器批准后再发送实际请求。
在该预检请求中,浏览器发送指示 HTTP 方法的 header 以及将在实际请求中使用的 headers。服务器还可以通知客户端是否应随请求发送凭据,比如 cookie 和 HTTP 身份验证。
Origin
Access-Control-Allow-Origin
Access-Control-Request-Method
Access-Control-Request-Headers
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Allow-Credentials
Access-Control-Max-Age
Access-Control-Expose-Headers
Request header
Origin
Access-Control-Request-Method
实际请求将使用的 HTTP methodAccess-Control-Request-Headers
实际请求将使用的 HTTP headers(浏览器自取)
Origin
可用于预检请求、普通请求。在任何 access control request 中始终会发送 Origin
header。
Access-Control-Request-*
header 仅在预检请求中用到,即 HTTP OPTIONS,是支持 CORS 的浏览器帮我们设置的,在发送实际请求时并不会包含它们。也就是说,使用 cross-origin 功能(如 Fetch 或 XMLHttpRequest)的开发人员不用以编程的方式设置任何 cross-origin sharing request headers。
Response header
Access-Control-Allow-Origin
重点介绍Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Allow-Credentials
重点介绍Access-Control-Max-Age
指示预检请求的结果可以缓存多长时间,单位是秒Access-Control-Expose-Headers
将指定的标头添加到允许 JavaScript 访问的白名单中
第2个和第3个都用于对预检 request 的 response。
Access-Control-Allow-Origin
Access-Control-Allow-Origin
取值,有两种情况:
单 origin
虽然 <origin>
的值只能是单个 origin,但服务器通常会利用白名单让其值随 request Origin
header 的值而动态改变。此时,response 会包含 Vary: Origin
header 以说明服务器的动态策略。
*
通配符
*
通配符Access-Control-Allow-Origin: *
适用于没有 credentials 的 request。此时,response 不会用任何 Set-Cookie
header 设置 cookie。
credentials,凭证,最常见的是
Cookie
header
凭据请求(credentialed request)带有 HTTP cookies 或 HTTP Authentication。
CORS 预检请求绝不能包含凭据
对预检请求的响应必须指定
Access-Control-Allow-Credentials: true
,才会在发实际请求的时候,使用凭据默认情况,在 cross-origin 的 XMLHttpRequest 或 Fetch 调用中,浏览器不会发送 credentials,除非 request 的
credentials
标志为true
当响应 credentialed request 时,以下 header 的值一定不能是 *
。
Access-Control-Allow-Origin
的值只能是单个 originAccess-Control-Allow-Methods
的值必须指定明确的 method name listAccess-Control-Allow-Headers
的值必须指定明确的 header name listAccess-Control-Expose-Headers
的值必须指定明确的 header name list
对于包含 credential 的 request:
如果 request 包含 credential,且 response 包含
Access-Control-Allow-Origin: *
,则浏览器会阻止访问 response,并在报告 CORS 错误如果 request 包含 credential,且 response 包含特定 origin
Access-Control-Allow-Origin: https://xxx.com
,则浏览器将允许该 origin 访问 response
Access-Control-Allow-Credentials
Access-Control-Allow-Credentials
该 header 表示是否向 request 公开 response,当 request 的 credentials
标志为 true
时。
当该 header 作为对预检请求的 response 时,表示实际请求是否可以带 HTTP credentials
当该 header 作为对带 credentials 的 GET 请求的 response 时(因为简单的 GET 请求不会被预检),如果 response 没有随资源返回
Access-Control-Allow-Credentials
header,则浏览器会忽略此 response,且不会把它返回给 web 内容
主要参考
WHATWG Fetch spec: HTTP CORS protocol:该规范描述了 CORS 目前在浏览器中的实现方式
现在,CORS 规范作为 WHATWG 的 Fetch Living Standard 的一部分包含在内
2014 年 1 月,被接受为 W3C Recommendation
2009 年 3 月,该草案更名为 Cross-Origin Resource Sharing
2006 年 5 月,W3C 的 WebApps 工作组提交了第一份 W3C 工作草案
2004 年 3 月,首次提出 cross-origin 支持,是允许 VoiceXML 浏览器进行安全的跨源数据请求
Last updated