跨浏览器 跨域资源共享 解决方案

前言

  通过XHR实现ajax通信的一个主要限制是 跨域安全策略。XHR对象只能访问与包含他的页面位于同一个域的资源。当发起一个资源请求的时候,请求头会带有一个 Origin头部,响应头会带有一个Access-Origin-Allow-Origin,如下:

Origin:http://www.test.com
Access--Control-Allow-Origin: http://www.test.com
// Access--Control-Allow-Origin: * // 代表公共资源

如果这个头部和Origin头部不相符合的时候,浏览器会驳回请求。于是就出现了跨域请求技术,下面是几种方式的总结.

实现一:跨浏览器的CORS

 1 function createCORSRequest(method,url) {
 2   var xhr = new XMLHttpRequest();
 3   if ("withCredentials" in xhr){
 4     xhr.open(method,url,true);
 5   }else if(typeof XDomainRequest!== "undifined"){
 6     xhr=new XDomainRequest();
 7     xhr.open(method,url);
 8   }else{
 9     xhr=null;
10   }
11   return xhr;
12 }
13 
14 var request=createCORSRequest('get','http://www.test.com');
15 if(request){
16   request.onload=function(){
17     // onreadystatechange检测成功
18     // 处理 requset.responseText
19   }
20   request.onerror=function(){
21     // 处理请求失败
22   }
23   requset.send(null);
24 }

上面是跨浏览器的实现方式,下面分析一下:

IE对CORS的实现

  IE8中引入了XDR(XDomainRequest)类型,此类型和XMLHttpResquest相似,但是可以实现安全的跨域通信。

不同之处:

①  不能通过setRequestHeader()设置自定义头部,只能设置请求头部信息的Content-Type字段,   xhr.contentType  

②  不能访问响应头信息,即调用getAllResponseHeaders()总是返回空字符串

③  不能发送和接受cookie

XDR对象的方法

①  open() 只接受两个参数,所有XDR请求都是异步的

②  send() 同XHR对象一样

其他事件

 1 var xdr=new XDomainRequest();
 2 xdr.onload=function(){
 3   //  xdr.responseText 响应的原始文本
 4   // 无法确定 响应的状态代码,即无 xhr.readyState和xhr.status
 5 }
 6 xdr.onerror=function(){
 7   alert("An error occurred.");
 8 }
 9 xdr.open('get',"url");
10 xdr.send(null);

其他浏览器对CORS的实现

  FireFox3.5+,Safari4+,Chrome等等都实现了原生CORS的支持。但是默认情况下,跨域请求不提供凭据,可以设置withCredentials表示带凭据的请求

于是,设置跨浏览器的CORS的时候,可以先检测是否带  withCredentials 属性,若无,再检测是否存在XDomainRequest对象。

实现二: 图像Ping

  可行性:网页可以从任何网页中加载图像,不用担心跨域问题。

  具体实现:利用 img 标签,动态创建图像。

1 var img=new Image();
2 img.onload=img.onerror=function(){
3   alert("done");
4 }
5 img.src="http://www.example.com/test?name=Kasmine";

   这里创建了一个Image实例,通过 img.src 向服务器发起GET请求(参数为name),服务器收到请求后,通过对请求url的解析,判断请求内容。

  应用:图像Ping主要用于用户点击页面或者浏览量的统计。

  缺点:只有get请求,不能访问服务器的响应文本

实现三: JSONP

  jsonp :“JSON with padding”顾名思义就是 包含在函数回调的json数据。具体实例如下:

1 function handleResponse(response) {
2   // 处理 response
3 }
4 var script=document.createElement("script");
5 script.src='http://www.example.com?callback=handleResponse';
6 document.body.insertBefore(script,document.body.firstChild);

<script>标签和<img>标签一样,不受访问域的限制。首先我们创建一个 script 元素,插入到页面后立刻执行。客户端定义了一个名为handleResponse的回调函数,向 http://www.example.com 发起GET请求,服务器端进行响应:

callback({"name":"Nicholes"});

客户端在响应到来时,会调用 回调函数 handleResponse

实现四:修改document.domain跨子域

  两个域名必须属于同一个基础域名

实现五:通过使用HTML5的window.postMessage方法来传送数据

始终使用origin和source属性验证发件人的身份

1 窗口A:
2 window.postMessage(msg,urlOfB);
3 窗口B:
4 window.onmessage(event){ 
5      var data=event.data;
6      var origin=event.origin;
7 }

小结 

  同源策略是XHR的一个约束,他要求“相同的域,相同的端口,相同的协议”才能进行通信。于是就出现了跨域访问的技术。

实现 跨域还有其他的方法,在这里就不多说了,日后学习到了,再继续补上~

原文地址:https://www.cnblogs.com/kasmine/p/6440571.html