也谈跨域数据交互解决方案

先来句题外话,最开始Ajax应该是用来特指用XMLHttpRequest传输数据这门技术,但就像最近大家把一切web新技术都归到html5名下一样,现在一切异步获取数据的手段都被人称之为Ajax。

由于JavaScript同源策略的存在,跨域数据交互是个老生常谈的话题了。网上相关文章很多,不过随着时间的推移和浏览器的更新,一部分解决方案已经不适用了,同时也出现了一些更好的方法。抛开纯服务器Proxy这种跟前端没什么关系的方案不说,这里简单总结下常见的其他几种方式。

JSONP

JSONP是最常见的跨域数据交互的方式,原理是html的script标签可以加载并执行其他域JS文件。站点B把要提供的数据作为参数传给一个站点A定义的全局函数,站点A引用这个文件就可以跨域获取数据了,A站还可以把少量参数放在script标签的src里提交给B站。外链JS这种方案只支持GET,受IE下url长度不能超过2083个字节的限制和出于安全考虑,一般不用来提交数据。

有人通过后端Proxy使得这种方式可以获取任意页面内容,还增加了对POST的支持,如:

HTML<script type="text/javascript" src="http://www.ajax-cross-domain.com/cgi-bin/ACD/ACD.js?uri=(http://www.google.com)"></script>
<script type="text/javascript">
    alert(ACD.responseText);
</script>
<script type="text/javascript" src="http://www.ajax-cross-domain.com/cgi-bin/ACD/ACD.js?uri=(http://216.92.131.147/dotserv/ACD/runit/post.cgi)&method=post&postdata=(name=fred&[email protected])"></script>
<script type="text/javascript">
    alert(ACD.responseText);
</script>

实际上这个方案是借助后端把任意页面输出为JS变量,后端根据url中相关标识来决定请求方式和参数,并不能解决大数据提交问题。

原生表单+Redirect+Callback

原生的form表单支持提交数据到其他域,我们只需要把form的target指向页面上的隐藏iframe,那就实现了无刷新提交,剩下的问题就是怎么获取提交后的结果。例如站点A表单提交数据到站点B,通常我们会在站点B处理完请求,重定向到站点A下某个Proxy页面,并在url带上参数标识处理结果。接着,A站下的Proxy页面就可以解析url参数,传给父页面的Callback函数来处理了。

Flash

利用flash的URLLoader,也可以轻松实现跨域数据交互。只要站点B的跨域策略文件(crossdomain.xml)中包含了站点A,A站就可以获取B站的数据,提交数据给B站。我们可以把JS和flash的交互封装一下,更方便的使用。这里有一个别人封装好的版本,使用起来和原生的XMLHttpRequest几乎一模一样:

JSvar req;
function callback() {
   if (req.readyState == 4) {
     try {
       if (req.status != 200) {
           alert(‘error detected 1‘);
       } else {
         alert("got data: "+req.responseText);
       }
     } catch(e) {
         alert(‘error detected 2‘);
     }
   }
}
function test_get() {
  req = new CrossXHR();
  req.onreadystatechange = callback;
  req.open(‘GET‘, ‘http://www.pliantdev.com/support/test.xml‘);
  req.send();
}

Iframe+XMLHttpRequest

如果站点B有一个proxy页面,用原生Ajax(XMLHttpRequest)对B站其他页面进行各种数据交互,那么我们在A站用iFrame引入这个proxy页面,只需要解决iFrame跨域问题就可以了。实际上,如果A和B属于相同大域,设置两边的document.domain为根域名就OK了;如果是完全不同的两个域,也有许多现成的解决方案,例如经典的window.name。更妙的是,除开IE6、IE7,几乎所有现代浏览器都支持用window.postMessage实现不同iFrame的数据通讯。pmxdr就是这样一个库,利用postMessage把数据传给隐藏的站外iFrame来实现跨域Ajax,libxdr对它进行了进一步的封装,使之更好用:

JSvar req = new XDR();
req.open("POST", "http://code.eligrey.com/pmxdr/libxdr/demo.php");
req.setRequestHeader("Content-Type",
    "application/x-www-form-urlencoded");
req.onload = function() {
    alert(this.responseText); // alerts "foo is bar"
};
request.send("foo=bar");

值得注意的是,这种方案只需要在站点B部署一个proxy页面,其他任意站点都可以通过这个页面与之交互,不太安全,这一点pmxdr考虑到了,在pmxdr-host.js里有一个变量alwaysTrustedOrigins,它是一个数组,支持用正则定义允许交互的站点。

终极解决方案:CORS

实际上,除了IE6、IE7,大部分现代浏览器已经支持了跨域资源共享(Cross-Origin Resource Sharing,简称:CORS)标准,这可谓是跨域Ajax的终极解决方案。有了这个标准,只需要在Response Header里加上这么一条,就可以轻松跨域了:

Access-Control-Allow-Origin: http://hello-world.example

这个header定义允许哪些域跟自己交互,如果定义为*就表示允许任何域,这么做当然是不推荐的。在除IE之外的标准浏览器,这样就可以跨域Ajax了。对于IE,需要换用新增的XDomainRequest对象来发送请求,其它都类似。另外还有几个header可以用来设置允许的提交方式等信息,如果要支持认证或者提交xml等格式的数据给服务器,则需要预请求,这里有更多说明。

总结

不同的方案有各自不同的使用场景,谁好谁坏不能一概而论。一般的,跨域获取数据个人习惯用JSONP,跨域提交数据个人习惯用表单+Callback。随着现代浏览器的普及,原生xhr也可以尝试下,flash可以作为替补降级用。最后,如果要选用一个封装了多种跨域实现的库,可以考虑下Yui3的io组件

本文提到一些组件链接:

时间: 2024-10-08 21:19:00

也谈跨域数据交互解决方案的相关文章

ASP.Net WebAPI与Ajax进行跨域数据交互时Cookies数据的传递

前言 最近公司项目进行架构调整,由原来的三层架构改进升级到微服务架构(准确的说是服务化,还没完全做到微的程度,颗粒度没那么细),遵循RESTFull规范,使前后端完全分离,实现大前端思想.由于是初次尝试,中途也遇到了不少问题.今天就来讨论一下其中之一的问题,WebAPI与前端Ajax 进行跨域数据交互时,由于都在不同的二级域名下(一级域名相同),导致Cookies数据无法获取. 最开始通过头部(Header)将Cookies传输到其WebAPI,也能解决问题. 下面讲述另外一种解决方案. 解决过

ASP.Net中关于WebAPI与Ajax进行跨域数据交互时Cookies数据的传递

本文主要介绍了ASP.Net WebAPI与Ajax进行跨域数据交互时Cookies数据传递的相关知识.具有很好的参考价值.下面跟着小编一起来看下吧 前言 最近公司项目进行架构调整,由原来的三层架构改进升级到微服务架构(准确的说是服务化,还没完全做到微的程度,颗粒度没那么细),遵循RESTFull规范,使前后端完全分离,实现大前端思想.由于是初次尝试,中途也遇到了不少问题.今天就来讨论一下其中之一的问题,WebAPI与前端Ajax 进行跨域数据交互时,由于都在不同的二级域名下(一级域名相同),导

JSONP -- 跨域数据交互协议

一.概念 ①传统Ajax:交互的数据格式——自定义字符串或XML描述: 跨域——通过服务器端代理解决. ②如今最优方案:使用JSON格式来传输数据,使用JSONP来跨域. ③JSON:一种数据交换格式.基于纯文本.被原生JS支持.    格式:两种数据类型描述符:大括号{ }.方括号[ ].分隔符逗号.映射符冒号.定义符双引好. ④JSONP:一种跨域数据交互协议,非官方. 1.Web页面调用js文件,可跨域.扩展:但凡有src属性的标签都具有跨域能力. 2.跨域服务器 动态生成数据 并存入js

JSONP(跨域请求) —— 一种非官方跨域数据交互协议

1.JSONP的作用 由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名.协议.端口)的资源,为 了实现跨域请求,可以通过script标签实现跨域请求,然后再服务器端输出JSON数据并执行回调函 数,从而解决了跨域的数据请求. JSONP协议的一个要点:允许用户传递一个callback参数给服务器端,然后服务器端返回数据时 会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自 动处理返回函数了. 2.如何使用JSONP? 在客户端

No &#39;Access-Control-Allow-Origin&#39; header is present之跨域问题及解决方案

如图,是在chome浏览器的Console中显示的信息,很明显,No 'Access-Control-Allow-Origin' header is present on the requested resource这句话表示出现了跨域请求问题,那么什么是跨域请求呢? 一.何为“跨域”? 跨域是浏览器对于javascript的同源策略的限制,一般我们使用ajax发送请求时会出现这种情况,举个栗子:A网站有一个请求路径为http:ip1:port1/aa,我们希望使用Ajax来获得B网站中的特定内

JWT跨域身份验证解决方案

JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案.本文介绍JWT的原理和用法. 1. 当前跨域身份验证的问题 Internet服务无法与用户身份验证分开.一般过程如下.1.用户向服务器发送用户名和密码.2.验证服务器后,相关数据(如用户角色,登录时间等)将保存在当前会话中.3.服务器向用户返回session_id,session信息都会写入到用户的Cookie.4.用户的每个后续请求都将通过在Cookie中取出session_id传给服务器.5.服务器收到session_

理解跨域及常用解决方案

跨域,相信大家无论是在工作中还是在面试中经常遇到这个问题,常常在网上看到别人所整理的一些方法,看似知道是怎么回事,但如果没有动手实践过,总觉得自己没有真正的掌握,在这里,通过自己认真思考整理一些常用的方法. 跨域的产生 不用多讲,作为一名前端开发人员,相信大家都知道跨域是因为浏览器的同源策略所导致的.所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源.浏览器引入同源策略主要是为了防止XSS,CSRF攻击. CSRF(Cross-site reque

extjs_02_grid(显示本地数据,显示跨域数据)

1.显示表格 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' start

跨域通信的解决方案JSONP

在web2.0时代,熟练的使用ajax是每个前端攻城师必备的技能.然而由于受到浏览器的限制,ajax不允许跨域通信. JSONP就是就是目前主流的实现跨域通信的解决方案. 虽然在在jquery中,我们可以通过$.ajax的dataType设置为jsonp来调用jsonp,但是jsonp和ajax的实现原理一个关系都木有.jsonp主要是通过script可以链接远程url来实现跨域请求的.如: <script src="http://jsonp.js?callback=xxx"&g