cors
运行在 http://domain-a.com
的JavaScript代码使用XMLHttpRequest
来发起一个到 https://domain-b.com/data.json
的请求。
出于安全性,浏览器限制脚本内发起的跨源HTTP请求。 XMLHttpRequest遵循同源策略,这意味着应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。
简介
跨源资源共享是一种基于HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它origin(域,协议和端口),这样浏览器可以访问加载这些资源。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
CORS应用场景
- 前文提到的由
XMLHttpRequest
或 Fetch 发起的跨源 HTTP 请求 - Web 字体 (CSS 中通过
@font-face
使用跨源字体资源)。网站可以发布 TrueType 字体资源,并只允许已授权网站进行跨站调用 - 使用
drawImage
将 Images/video 画面绘制到 canvas
访问控制场景
简单请求
某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”。简单请求满足的条件,本文略过,有很多官方资料介绍。请求的过程如下:
- 请求Header字段
Origin
表明该请求来源于http://foo.example
- 服务端返回的
Access-Control-Allow-Origin: *
表明,该资源可以被任意外域访问。
如果服务端仅允许来自 http://foo.example
的访问,应返回:Access-Control-Allow-Origin: http://foo.example
。这样,除了 http://foo.example
,其它外域均不能访问该资源
预检请求
与简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS
方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。
1.浏览器检测到,从 JavaScript 中发起的请求需要被预检。首先发起了一个使用 OPTIONS
方法的预检请求。
请求
1 |
|
响应
1 |
|
2.预检请求完成之后,发送实际请求。
附带身份凭证的请求
一般而言,对于跨源 XMLHttpRequest
或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest
的某个特殊标志位。
本例中,http://foo.example
的某脚本向 http://bar.other
发起一个GET 请求,并设置 Cookies:
1 |
|
因为这是一个简单 GET 请求,所以浏览器不会对其发起“预检请求”。但是,如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true
,浏览器将不会把响应内容返回给请求的发送者。
过程如下:
请求
1 |
|
响应
1 |
|
对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin
的值为“*
”。这是因为请求的首部中携带了 Cookie
信息,如果 Access-Control-Allow-Origin
的值为“*
”,请求将会失败。而将 Access-Control-Allow-Origin
的值设置为 http://foo.example
,则请求将成功执行。另外,响应首部中也携带了 Set-Cookie 字段,尝试对 Cookie 进行修改。如果操作失败,将会抛出异常。
gin-cors
1 |
|