CORS 跨域
虽然一直知道跨域,但也仅限于知道什么情况下会出现跨域的问题,没有实践过如何实现跨域。最近写代码正好碰到了需要跨域的需求,正好学习一下。实现跨域有很多种方法,常见的有 CORS,JSONP。这里我仅仅是说明如何使用 CORS 进行跨域。
请求分类
请求分为简单请求和非简单请求,满足以下条件的为简单请求,否则为非简单请求。
一、请求方法是以下几种
- HEAD
- GET
- POST
二、HTTP的头信息不超出以下几种字段
(不包括 User Agent 自动增加的头部,如 Connection
,User-Agent
,详情见forbidden-header-name)
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Contnet-Type 为
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
中的一个。
简单请求
在简单请求的情况,浏览器在发出CORS请求头部中会自动增加一个 Origin
字段。
如果 Origin
指定的源不在许可的范围里面,服务器就会返回一个正常的 HTTP 响应。如果浏览器发现回应的信息没有 Access-Control-Allow-Origin
,浏览器就会抛出一个错误,并会被 XMLHttpRequest
的 onerror
捕获。
注意:此时 HTTP 返回码仍然可能是 200。
如果是允许返回的域,则服务器返回的字段中会有以下几个字段(其中,肯定会有 Access-Control-Allow-Origin
,另外的两个根据相应情况而定。
(1) Access-Control-Allow-Origin
表明允许的 Origin
,当时 *
的时候表示接受任何域的请求。
(2) Access-Control-Allow-Credentials
表明是否允许发送 cookie
。允许下添加 Access-Control-Allow-Credentials: true
,否则不包含该字段,该字段不能设置为 false
。如果要浏览器发cookie
,还需要浏览器方面做出一些配置。
这样就可以发送 cookie
了,另外需要注意的是,如果要发送 cookie
,服务器返回的 Access-Control-Allow-Origin
不能是 *
,必须是确定的域名。cookie
的传送依然遵循同源政策。
(3) Acess-Control-Expose-Headers
可被 getResponseHeader
拿到的额外的字段。
本来就可以拿到的字段有:
非简单请求
当发送非简单请求的时候,会先发送一个 preflight
请求,看这个请求是否被允许。
如下所示就是一个 prefilight
请求
注意到有两个特殊字段
(1) Access-Control-Request-Method
表明该请求所用到的 HTTP 方法
(2) Access-Control-Request-Headers
表明额外发送的头信息字段,这里是 x-requested-with
,多个字段用逗号隔开。
如果服务器允许该跨域请求,会做出相应的回应。
如果服务器返回普通的响应,则浏览器认为跨域不被允许,于是会抛出错误。
这里有几个新的字段之前没看到过
(1) Access-Control-Allow-Headers
允许的额外头部
(2) Access-Control-Allow-Methods
允许的 HTTP 请求方法
另外,还有可能会返回一下的字段
(1) Access-Control-Allow-Credentials
(2) Acess-Control-Max-Age
指明本次 preflight
的有效时间(秒),在有效时间内不用再次发送 preflight
请求。
接着浏览器就会发送正常的请求:
接着服务器再返回请求
参考资料
更新记录
- 2017 年 8 月 16 日修改对简单请求的描述