浅谈跨域

引言

  使用XHR对象进行Ajax通讯的主要限制,就是跨域的资源访问。默认情况下,XHR只能访问与包含它的页面位于同一个域中的资源。这种安全策略可以预防某些恶意的行为。但是,实现合理的跨与请求对于开发某些应用程序也是必要的。下面,我们就来介绍下关于跨域这方面的知识。

 CORS简介

  CORS(跨域资源共享)是W3C定义的一个工作草案,定义了在必须进行跨域资源访问时,浏览器与服务器之间的通讯。CORS背后的思想是这样的:使用自定义的Http头部让浏览器和服务器进行通讯,从而决定响应是成功的还是失败的。

  例如我们使用GET或者POST发送一个请求时,它默认是没有自定义头部的。在发送该请求时,需要额外添加一个Origin头部(包含请求页面的源信息:协议、域名和端口),以便服务器根据这个头部来决定是否给予响应。

  例如:我们需要跨域访问http://www.nczonline.net。那么浏览器会将Origin设置为这个URL地址。如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin中回发相同的源信息。如果没有这个头部,或者这个头部源信息不匹配,浏览器就会拒绝进行跨域的请求。

  下面介绍一个完整的例子,如下:

  假设我们页面或者应用已在 http://www.test1.com 上了而我们打算从 http://www.test2.com 请求提取数据。一般情况下,如果我们直接使用 AJAX 来请求将会失败,浏览器也会返回“源不匹配”的错误,这就是跨域。

  利用 CORS, http://www.test2.com 只需添加一个标头,就可以允许来自 http://www.test1.com 的请求,下图是我在PHP中的 hander() 设置,“*”号表示允许任何域向我们的服务端提交请求
     
IE对CORS的实现

  IE8中引入了XDR(XDomainRequest)对象来支持跨域的请求。这个对象与XHR对象类似,但它可以实现安全可靠的跨域访问。但是XDR对象和XHR对象相比还是有一些不同的。主要在以下几点。

  1、cookie不会随请求发送,也不会随响应返回。

  2、只能设置头部信息中的Content-Type字段。

  3、不能访问头部响应信息。

  4、只支持GET和POST请求。

  注意:XDR对象open方法只有两个参数。请求的类型和URL.所有的XDR都是异步进行的。请求返回后,会触发onload事件,响应的数据保存在responseText中。例子如下:

1 domainRequest = new XDomainRequest();
2 domainRequest.open(method, url);
 this.domainRequest.send(null);
3 //注册相关回调函数 4 this.domainRequest.onload = callback; 5 this.domainRequest.onerror = failback;

  注意:由于导致XDR失败的因素很多,建议使用onerror事件来处理异常。

其他浏览器对CORS的支持

  Firefox 3.5+、Safiri 4+、Chrome、iOS系统的Safiri以及Android平台的WebKit都XMLHttpRequest对象实现了CORS的原生支持。在尝试打开不同来源的资源时,无需额外编写代码户可以触发这个行为。要请求位于另一个域中的资源,使用标准的XHR对象并在open中传入绝对路径即可。(http://.....)。

  与IE中的XDR对象不同,通过跨域XHR对象可以访问status和statusText属性,而且还支持同步请求。跨域XHR对象也存在一些限制。如:

  不能使用setRequestHander()设置自定义头部

  不能发送和接收cookie

  调用getAllResponseHeaders()总会返回空字符串

跨浏览器的CORS

  各种浏览器对CORS的支持程度都不一样。但所有浏览器都支持简单的请求。下面通过代码来介绍下跨浏览器的CORS实现。如下:

 1 /**
 2  * 跨域版本的Ajax.在IE8-IE10中是使用XDomainRequest来实现CORS.注意:IE11不支持XDomainRequest
 3  * 其他主流浏览器可以使用XMLHttpRequest来实现跨域
 4  * method:调用ajax的方式:get/post
 5  * url:调用服务端方法的路径(asmx,controller都可).如:Login/CheckUser注意get,post时不要使用?Id=XX&Name=XX等形式
 6  **/
 7 function DomainAjaxInstance(method, url) {
 8     var domainRequest = new XMLHttpRequest();
 9     if ("withCredentials" in domainRequest) {
10         // 此时即支持CORS的情况
11         // 检查XMLHttpRequest对象是否有"withCredentials"属性
12         // "withCredentials"仅存在于XMLHTTPRequest2对象里
13         domainRequest.open(method, url, true);
14     }
15     //IE8,9中跨域访问对象XDR
16     else if (typeof XDomainRequest != "undefined") {
17         domainRequest = new XDomainRequest();
18         domainRequest.open(method, url);
19     }
20     else {
21         domainRequest = null;
22     }
23     //保存调用的相关参数
24     this.domainRequest = domainRequest;
25     this.method = method;
26     this.url = url;
27 }
28 
29 /**
30  * 跨域访问(跨域访问支持仅GET和POST)
31  * data:调用方法时传递的参数.只需要以对象形式{Id:"",Name:""}传递data参数即可,无参传递null
32  * callback:获取结果的回调函数
33  * failback:跨域调用出错时的回调函数
34  **/
35 DomainAjaxInstance.prototype.call = function (data, callback, failback) {
36     if (!(callback instanceof Function) || !(failback instanceof Function)) {
37         alert("调用call方法必须指定callback和failback方法");
38         return;
39     }
40     var query = null;
41     if (data !== null && (data instanceof Object)) {
42         query = appendParameters(data);
43     }
44     var type = this.method;
45     if (type.toLowerCase() == "post") {
46         this.domainRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
47         this.domainRequest.send(query);
48     }
49     else {
50         var url = this.url;
51         if (query !== null) {
52             url += (url.indexOf("?") == -1) ? "?" : "&";
53             url += query;
54         }
55         this.domainRequest.send(null);
56     }
57     //注册相关回调函数
58     this.domainRequest.onload = callback;
59     this.domainRequest.onerror = failback;
60 }
其他跨域技术
  JSONP

  JSONP是填充式JSON或者参数式JSON的缩写,是一种应用JSON的新方法。JSONP看起来和JSON差不多,只是被包含在函数调用中的JSON。一般调用方式是这样:callback({"name":"Nicolas"})。

  JSONP由两部分组成,回调函数和数据。回调函数是当响应到来的时应该在页面调用的函数。回调函数的名称一般都是在页面中指定的。数据就是传入回调函数的JSON数据。

下面展示一个典型的JSONP请求:

  http://freegeiop.net/json/?callback=handlerRsoponse(回调函数名称是:handlerRsoponse)。

  JSONP是通过动态<script>标签来使用的。使用时通过为<script>标签设定src属性是一个跨域的URL。这里的<script>标签与<img>标签类似,都有能力不限制的从其他域加载资源。

  当然JSONP也存在不足,主要表现在下面两点

  1、JSONP是从其他域加载代码执行的,如果其他域不安全,很可能会在响应中夹杂着恶意代码。所以使用JSONP时一定要确保安全可靠。

  2、要确定JSONP请求是否失败并不容易,现阶段开发人员只能使用定时器来检测是否接收到响应。

相关资料

  对于JSONP,下面两篇博文介绍的不错,推荐给大家。大家可以看看JQuery中怎么使用这种跨域技术的。

  http://kb.cnblogs.com/page/139725/

  http://justcoding.iteye.com/blog/1366102

转载于:https://www.cnblogs.com/dreamGong/p/4959401.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值