跨域之浏览器同源策略
定义:同源策略是指在不同源的资源不允许访问
源的定义:协议+主机+端口
举例:
http://www.baidu.com/index.html中有一个ajax请求 http://www.google.com/getUserInfo
由于host不一致,即www.baidu.com != www.google.com 因此浏览器判断非同源 将禁止访问
Tips:当ajax请求由于同源策略禁止的时候,request仍然会发送,也会收到response,只不过浏览器收到response后选择了忽略而已
同源策略限制的范围:
- Cookie、LocalStorage 和 IndexDB 无法读取。
- DOM 无法获得。
- AJAX 请求不能发送。
如何实现跨域访问之CORS
CORS是跨域资源共享的简写,是w3c的标准,用于当发生跨域请求的时候,需要浏览器和服务端同时支持才能访问非同源资源,是实现跨域请求最广泛的方案之一
浏览器将CORS请求分成两类:
简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:
- HEAD
- GET
- POST
(2)HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
这是为了兼容表单(form),因为历史上表单一直可以发出跨域请求。AJAX 的跨域设计就是,只要表单可以发,AJAX 就可以直接发。
凡是不同时满足上面两个条件,就属于非简单请求。
浏览器对这两种请求的处理,是不一样的。
简单请求:浏览器会在请求header中加上Origin字段,用于说明本次请求来自哪个源(协议+域名+端口)
服务器根据Origin字段判断是否允许访问,如允许访问则在response header中加入
Access-Control-Allow-Origin字段,标识允许哪些源访问
Access-Control-Allow-Credentials:标识是否允许发送cookie给服务器(CORS请求默认不允许cookie)
Access-Control-Expose-Headers:标识浏览器可以获取的额外的header字段(CORS请求返回后,默认浏览器只能获取六个header字段Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma)
非简单请求:此种请求会在正式请求之前加上一次预检请求(preflight),即通过一次options请求
在options请求的header中有以下字段
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
分别标识当前请求的源、方法、特殊的请求头
服务器会返回以下header字段
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000 //标识此次预检的有效期(单位秒),有效期内不必再次发出预检请求
预检通过后,接下来的流程同简单请求,request header加上origin, response header加上Access-Control-Allow-Origin
WKWebView中的跨域限制
H5所在位置分为本地加载、网络加载
一、H5在本地即在[NSBundle mainBundle]或者沙盒获取的文件
此时发送CORS简单请求header中的Origin为null
可通过设置WKWebView允许跨域
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init];
if (@available(iOS 10.0, *)) {
[config setValue:@YES forKey:@"allowUniversalAccessFromFileURLs"];
}
二、H5在服务器上
不可通过设置WKWebView进行跨域请求
iOS12在WKWebView的预检中需要返回Access-Control-Expose-Headers value不可指定为*
否则无法发起正常通信请求