是由W3C提出的一个用于浏览器以XMLHttpRequest方式向其余源的服务器发起请求的规范。不一样于JSONP,CORS是以Ajax方式进行跨域请求,须要服务端与客户端的同时支持。目前CORS在绝大部分现代浏览器中都是支持的(IE浏览器不能低于10)html
CORS标准定义了一个规范的HTTPHeaders来使得浏览器与服务端之间能够进行协商来肯定某个资源是否能够由其余域的客户端请求得到。尽管不少的验证与鉴权是由服务端完成,可是本质上大部分的检查和限制仍是应该由浏览器完成。对于开发者来讲,CORS通讯与同源的AJAX通讯没有差异,代码彻底同样。浏览器一旦发现请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感受。所以,实现CORS通讯的关键是服务器。只要服务器实现了CORS接口,就能够跨源通讯。通常来讲CORS会分为简单请求与预检请求两大类。api
当浏览器的请求方式知足如下的任意一个条件的时候,浏览器会先发送一个OPTION请求,用来与目标域名服务器协商决定是否能够发送实际的跨域请求。OPTIONS请求头部中会包含如下头部:Origin、Access-Control-Request-Method、Access-Control-Request-Headers。
服务器收到OPTIONS请求后,设置Access-Control-Allow-Origin、Access-Control-Allow-Method、Access-Control-Allow-Headers头部与浏览器沟通来判断是否容许这个请求。跨域
请求方法不是下列之一:浏览器
请求头中的Content-Type请求头的值不是下列之一:缓存
不然就是预检请求。预检请求会在正式通讯以前,增长一次HTTP查询请求。浏览器会先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可使用哪些HTTP动词和头信息字段。只有获得确定答复,浏览器才会发出正式的XMLHttpRequest请求,不然就报错。预检请求的发送请求:服务器
"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。请求头信息里面,关键字段是Origin,表示请求来自哪一个源。
除了Origin字段,"预检"请求的头信息包括两个特殊字段:cookie
预检请求的返回:app
一旦服务器经过了预检请求,之后每次浏览器正常的CORS请求,就都跟简单请求同样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。cors
当浏览器的请求方式是HEAD、GET或者POST,而且HTTP的头信息中不会超出如下字段:url
浏览器会将该请求定义为简单请求,对于简单的跨域请求或者经过了预检的请求,浏览器会自动在请求的头信息加上Origin字段,表示本次请求来自哪一个源(协议 + 域名 + 端口),即代表这是一个跨域请求。服务端会获取到这个值,根据相应的跨域规则而后判断是否赞成此次请求并返回。典型的请求头尾:
// 请求 - GET /cors HTTP/1.1 - Origin: http://localhost:8080 - Host: api.alice.com - Accept-Language: en-US - Connection: keep-alive - User-Agent: Mozilla/5.0...
若是服务端容许,在返回的头信息中会多出几个字段:
// 返回 Access-Control-Allow-Origin: http://localhost:8080 Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: Info Content-Type: text/html; charset=utf-8
须要注意的是,若是要发送Cookie,Access-Control-Allow-Origin就不能设为*,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其余域名的Cookie并不会上传,且原网页代码中的document.cookie也没法读取服务器域名下的Cookie。
若是服务端拒绝了调用,即不会带上 Access-Control-Allow-Origin 字段,浏览器发现这个跨域请求的返回头信息没有该字段,就会抛出一个错误,会被 XMLHttpRequest 的 onerror 回调捕获到。这种错误没法经过 HTTP 状态码判断,由于回应的状态码有多是200。
服务器端对于跨域请求的处理流程以下: