同源概念
为了保证用户信息的安全,防止恶意的网站窃取数据,现行所有浏览器都实行 “同源策略”。 同源是指:协议相同、域名相同、端口相同
但是在实际应用中,我们常常需要向非同域站点发送请求,这个时候就需要应用到 “CORS” 来解决跨域问题了
CORS(跨域资源共享)
CORS是一个W3C标准,全称是 “跨域资源共享”(Cross-origin resource sharing)
它允许浏览器向跨域服务器发起 XMLHttpRequest请求,从而解决同源限制问题
CORS请求: 简单请求、非简单请求
简单请求
同时满足以下条件,即属于简单请求:
- 请求方法是以下三种方法之一:
- HEAD
- GET
- POST
- HTTP 的头信息不超出以下几种字段
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type: 只限于 (application/x-www-form-urlencoded、multipart/form-data、text/plain)
复杂请求
非简单请求既是复杂请求
常见的复杂请求有:
- 请求方法为put或delete
- Content-Type字段类型为application/json
- 添加额外的HTTP Header,比如access_token
在跨域的情况下,复杂请求会先发起一次空body的OPTIONS请求,称为 “预检” 请求(preflight),用于向服务器发送请求权限信息,等预检请求被成功响应后(这里的成功不是有响应,而是返回的响应体允许跨域),才会再次发起真正的http请求
预检请求
非简单请求的CORS请求,会在正式通信之前,增加一次空body的HTTP查询OPTIONS请求,称为"预检"请求(preflight)
预检请求的请求体是空的,这样做是为了节约带宽,提高传输速率
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP方法和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错
预检请求的头信息包括以下几个必须的特殊字段:
- Origin:表示请求来自哪个源
- Access-Control-Request-Method:本次预检请求的请求方法
- Access-Control-Request-Header:本次请求所携带的自定义首部字段,该字段是一个逗号分隔的字符串
预检请求响应头
服务端收到预检请求后,检查了请求头的几个字段之后,便可以做出相应的回应:
// 服务器返回的响应头
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
-
Access-Control-Allow-Methods
必须字段,是一段由逗号分隔的字符串,表示服务器支持的
所有跨域请求的方法 (是所有支持的方法,而不是浏览器请求的方法,这是为了避免重复预检请求) -
Access-Control-Allow-Headers
如果浏览器请求包括
Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段 -
Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为
true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可 -
Access-Control-Max-Age
该字段可选。用来指定本次预检请求的有效期 (即对预检请求进行缓存)
在预检请求跨域通过时,在后续的CORS请求中。请求头总会有一个Origin字段,而服务器的响应,也都会有一个Access-Control-Allow-Origin字段
其他常见跨域解决方案
-
JSONP
-
CORS
-
iframe
-
postMessage
-
websocket
-
nginx代理
-
中间件代理