Cross-Origin Resource Sharing
Who should read this article?
Everyone, really.
More specifically, this article is for web administrators, server developers and front-end developers. Modern browsers handle the client side of cross-origin sharing, including headers and policy enforcement. But the CORS standard means servers have to handle new request and response headers.
What requests use CORS?
不是所有http请求,都会验证CORS的。普通的cdn加载js或者css文件,是不会触发CORS检查的。
This cross-origin sharing standard can enable cross-site HTTP requests for:
- Invocations of the
XMLHttpRequest
or Fetch APIs, as discussed above. - Web Fonts (for cross-domain font usage in
@font-face
within CSS), so that servers can deploy TrueType fonts that can only be loaded cross-site and used by web sites that are permitted to do so. - WebGL textures.
- Images/video frames drawn to a canvas using
drawImage()
. - CSS Shapes from images.
This is a general article about Cross-Origin Resource Sharing and includes a discussion of the necessary HTTP headers.
Cross-Origin Resource Sharing协议介绍
COR的实现标准就是CORS协议。
对于浏览器来说,COR请求都是Javascript发起的,COR请求有两种:
1、简单的COR请求,它可以直接向外域资源发起请求。它必须仅仅包含简单的方法和头,具体定义看[2] 6.1。
2、如果COR包含复杂的方法和头,它需要发出预检验(Preflight)请求,它先向资源服务器发出一个OPTIONS方法、包含“Origin”头的请求。该回复可以控制COR请求的方法,HTTP头以及验证等信息。只有该请求获得允许以后,才会发起真实的外域请求。
下面是一个简单的COR请求:
<script language="Javascript" type="text/javascript">
var client = new XMLHttpRequest();
client.open("GET", "http://bar.org/b")
client.onreadystatechange = function() { /* do something */ }
client.send()
</script>
假设这个请求所在页面的域是“http://foo.org”。 如果来自“http://bar.org/b”的回复包含这样的头:
Access-Control-Allow-Origin: http://foo.org
则表明,它允许来自“http://foo.org”的跨域请求。
下面的Javascript会发出预检验请求和真实请求:
<script language="Javascript" type="text/javascript">
var client = new XMLHttpRequest();
client.open("GET", "http://bar.org/b")
client.setRequestHeader('Content-Type','text/html')
client.onreadystatechange = function() { /* do something */ }
client.send()
</script>
由于“Content-type: text/html”不是一个简单的头,它会先向"http://bar.org/b"发出一个OPTIONS的HTTP请求。 回复可能包含这样的头:
Access-Control-Allow-Origin: http://foo.org
Access-Control-Max-Age: 3628800
Access-Control-Allow-Methods: GET,PUT, DELETE
Access-Control-Allow-Headers: content-type
"Access-Control-Allow-Origin"表明它允许"http://foo.org"发起跨域请求
"Access-Control-Max-Age"表明在3628800秒内,不需要再发送预检验请求,可以缓存该结果
"Access-Control-Allow-Methods"表明它允许GET、PUT、DELETE的外域请求
"Access-Control-Allow-Headers"表明它允许跨域请求包含content-type头
如果预检验请求获得通过,接下来Javascript就会发起真实的COR请求,过程跟简单的COR请求类似。
CORS协议的实现
现在HTML5的标准如火如荼的在制定和发展中,CORS作为HTML5的一部分,在大部分现代浏览器中有所支持,支持(部分支持)CORS协议的浏览器有IE8+, Firefox5+, Chrome12+, Safari4+
WEB跨域资源共享:Cross-origin Resource Sharing(CORS)
跨域资源共享(CORS)请求:通常CORS请求可分为两类,一类是简单请求,另一类则是预检请求。无论何种请求类型,只要服务端响应中未包含正确的首部如Access-Control-Allow-Origin: http://foo.example等,浏览器将报告错误。
简单请求:简单请求与普通请求相比,多了请求首部字段Origin,形如Origin: http://foo.example,服务端响应时则多了响应首部字段Access-Control-Allow-Origin,形如Access-Control-Allow-Origin: http://foo.example 或者 *。简单请求须满足所有下述条件:
- 使用下列方法之一:
GET
HEAD
POST
Content-Type
:仅POST方法的Content-Type值等于下列之一才算作简单请求:text/plain
multipart/form-data
application/x-www-form-urlencoded
- Fetch 规范定义了对 CORS 安全的首部字段集合,不得人为设置该集合之外的其他首部字段。该集合为:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink
Save-Data
Viewport-Width
Width
预检请求:需预检的请求必须首先使用 OPTIONS
方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求,如果服务端同意,再发送实际请求,这样可以避免跨域请求对服务器的用户数据产生未预期的影响。预检请求须满足所有下述条件:
- 使用了下面任一 HTTP 方法:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH
- 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
Accept
Accept-Language
Content-Language
Content-Type
(but note the additional requirements below)DPR
Downlink
Save-Data
Viewport-Width
Width
-
Content-Type
的值不属于下列之一:application/x-www-form-urlencoded
multipart/form-data
text/plain