CORS跨域资源共享,这个话题大家一定不陌生了,吃久了大转转公众号的深度技术好文,也该吃点儿小米粥溜溜胃里的缝儿了,今天咱们就再好好屡屡CORS跨域资源共享这个话题,大牛怡情小牛巩固,把这碗前端经久不凉的大碗茶,再细细的品一品。
“JSONP直接了当很豪爽,CORS细吮慢品大补汤”
在咱们前端的日常工作中,跨域比较常用的方式就是JSONP,JSONP呢就是通过script标签无同源限制的特点,在获取到需要的资源后自动执行回调方法的方式,而我们浏览器原生的CORS跨域,是通过“正当手段”得到服务器小姐姐首肯,大摇大摆获取跨域资源的方式,相比JSONP只能实现GET请求,CORS大法支持所有的请求类型,同时CORS是通过普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理,接下来我们就来说下这个CORS大法。
“整体概述,先摆个谱”
官方简略的: CORS(Cross-Origin Resource Sharing)跨域资源共享,主要思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定响应是成功还是失败,它允许了浏览器向跨源服务器发送请求,从而克服了同源的限制。
私下露骨的: 其实就是向服务器发送跨域请求时,浏览器自动针对普通请求和非普通请求进行区别对待,在请求头中加个Origin字段告诉服务器这个请求的源,通过服务器返回的响应头中Access-Control-Allow-Origin字段的值是不是请求中的Origin,来看服务器让不让咱请求到这资源。
“我是一些工作中不怎么用得到的基本知识,可我也是一条小生命啊”
CORS 浏览器的支持情况 :
浏览器端已经获得了良好的支持,所以实现CORS的关键就是服务器,只要实现了CORS的接口,就可以实现跨域通信。
IE对CORS的实现 :
IE8中引入了XDR(XDomainRequest),注意:
-
cookie不会随请求发送,也不会随响应返回
-
只能设置请求头部信息中的Content-Type字段
-
不能访问响应头部信息
-
只支持GET和POST请求
XDR对象的使用方法用户XHR对象非常类似,如下:
-
1 var xdr = new XDomainRequest();
3 xdr.onload = function() { 5 alert(xdr.responseText); 7 } 9 xdr.onerror = function() { 11 alert("error"); 13 } 15 xdr.open("get", "http://www.xxx.com/yyy/"); 17 xdr.send(null);
其他浏览器对CORS的实现
Firefox3.5+,Safari4+,Chorme,IOS版的Safari和Android平台下的WebKit都通过XmlHttpRequest实现了对CORS的支持。
-
1 var xhr = new XMLHttpRequest();
3 xhr.onreadystatechange = function () { 5 if(xhr.readyState == 4){ 7 if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ 9 console.log(xhr.responseText) 11 }else { 13 console.log('err' + xhr.status); 15 } 17 } 19 }; 21 xhr.open('get','http://www.xxx.com/zzz/',true); 23 xhr.send(null);
跨域XHR一些安全限制:
-
不能使用setRequestHeader()设置自定义头部
-
不能发送和接收cookie
-
调用获取所有头部信息的方法getAllReponseHeaders()方法会返回空字符串
“请求没有那么简单,每种都有她的习惯”
浏览器将CORS请求分成两类。
1.简单请求:
高大上版定义:
Simple requests
A simple cross-site request is one that meets all the following conditions:
The only allowed methods are: GET HEAD POST
Apart from the headers set automatically by the user agent (e.g. Connection,User-Agent, etc.), the only headers which are allowed to be manually set are:
Accept
Accept-Language
Content-Language
Content-Type
The only allowed values for the Content-Type header are:
application/x-www-form-urlencoded multipart/form-data text/plain
大意就是说:
-
请求方法是以下三种方法之一:HEAD,GET,POST
-
HTTP的头信息不超出以下几种字段:Accept,Accept-Language,Content-Language,Last-Event-ID
-
Content-Type只限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain
2.非简单请求:
非简单请求是那种对服务器有特殊要求的请求,除以上条件之外的都是非简单请求,条件如下:
-
使用了下面任一 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
“跨域请求分两队,差别对待也是醉”
在讨论"CORS对不同请求的处理"这部分内容时,我们同步跑起来一个nodejs的项目对照着理解,纸上谈兵终觉浅,要干大事还得码啊!
为了更加直观,我们为我们接下来要占用的两个端口配下代理:
-
127.0.0.1:8081 m.zhuanzhuan.com
-
127.0.0.1:8082 u.58.com
客户端nodejs脚本 client.js:
-
1 var http = require('http');
3 var fs = require('fs'); 5 var url = require