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

先来句题外话,最开始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=fred@fred.com)"></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组件。

本文提到一些组件链接:

  • AJAX Cross Domain(在服务端把任意网页转为JS变量)
  • Cross Domain XHR(基于flash,接口与xhr高度一致)
  • pmxdr(使用postMessage和iframe的跨域方案)
  • libxdr(pmxdr的再次封装,接口模拟IE的XDomainRequest)
  • Yui3的IO组件(基于flash或原生xhr的跨域方案)

posted on 2015-09-18 14:22 jsCoder_洋洋 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/zhuyang/p/4793176.html

也谈跨域数据交互解决方案相关推荐

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

    本文主要介绍了ASP.Net WebAPI与Ajax进行跨域数据交互时Cookies数据传递的相关知识.具有很好的参考价值.下面跟着小编一起来看下吧 前言 最近公司项目进行架构调整,由原来的三层架构改 ...

  2. Ajax跨域请求与解决方案

    同域与跨域请求 同域请求: 网络协议, 域名,端口号都一致,则为同域(同源)请求 http://www.sina.com.cn:8090/index.html 跨域请求: 浏览器对于javascrip ...

  3. Web学习之跨域问题及解决方案

    Web学习之跨域问题及解决方案 javascript/jquery 浏览数:161 2017-5-8 在做前端开发时,我们时常使用ajax与服务器通信获取资源,享受ajax便利的同时,也知道它有限制: ...

  4. 跨域的十种解决方案详解(总结)

    什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的. 广义的跨域: 1.) 资源跳转: A链接.重定向.表单提交 2.) 资源嵌入: <link>.&l ...

  5. 到底什么是跨域?附解决方案

    转载自 到底什么是跨域?附解决方案 什么是跨域 要了解跨域,先要说说同源策略. 同源策略是由 Netscape 公司提出的一个著名的安全策略,所有支持 JavaScript 的浏览器都会使用这个策略. ...

  6. 第四节:跨域请求的解决方案和WebApi特有的处理方式

    一. 简介 前言: 跨域问题发生在Javascript发起Ajax调用,其根本原因是因为浏览器对于这种请求,所给予的权限是较低的,通常只允许调用本域中的资源, 除非目标服务器明确地告知它允许跨域调用. ...

  7. 第十八节:跨域请求的解决方案和WebApi特有的处理方式

    一. 简介 前言: 跨域问题发生在Javascript发起Ajax调用,其根本原因是因为浏览器对于这种请求,所给予的权限是较低的,通常只允许调用本域中的资源, 除非目标服务器明确地告知它允许跨域调用. ...

  8. php后台跨域token,JSON Web Token(JWT)目前最流行的跨域身份验证解决方案(PHP)类...

    JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案,下面我自己封装了一个PHP的Jwt类,直接复制即可使用,无需composer安装包: 常规的身份验证流程为: 该方案的最大的短 ...

  9. 前端跨域请求及解决方案

    什么是跨域请求 在前端开发编码过程中,常见的HTML标签例如:a.form.img.script.link.iframe以及ajax操作都可以指向一个资源地址或者说发起一个资源请求,那么这里所说的请求 ...

最新文章

  1. 使用TensorFlow1.0及以上版本的问题
  2. Nginx源码分析:3张图看懂启动及进程工作原理
  3. android动态监听事件,Android-常见的事件监听
  4. Prim算法和Kruskal算法
  5. c语言第四版课后答案第三章3.4,算法与数据结构C语言版课后习题答案(机械工业出版社)第3,4章 习题参考答案...
  6. python 内推_[宜配屋]听图阁
  7. Java主函数要放在哪个类里_JAVA:主函数一定要放在静态内部类里吗
  8. python学习之网络编程
  9. Vue角色的权限管理
  10. 水电远程预付费管理系统
  11. c语言词法分析程序设计,c语言词法分析器的简单实现 词法分析器的设计与实现...
  12. 使用Nexus在Windows中搭建Maven私服
  13. FIT2CLOUD飞致云正式推出X-Lab孵化器,首期发布两款开源软件
  14. 用Python实现从Oracle到GreenPlum的表结构转换
  15. 谈一谈凑单页的那些优雅设计
  16. STM32 内核复位 与 系统复位 区别及程序实现
  17. 镜头焦距与拍摄距离以及拍摄范围的关系
  18. CLIP CLAP
  19. [CTS2019]氪金手游(容斥+树形背包DP)
  20. Globalsign和Symantec SSL证书哪家好

热门文章

  1. android 自定义圆形pop,Android布局自定义Shap圆形ImageView可以单独设置背景与图片...
  2. linux 内核空间 缺页,Linux-3.14.12内存管理笔记【缺页异常处理(1)】
  3. python中异或运算_python – 基于ID列表有效计算XOR(^)校验和的方法
  4. Linux笔记-shell脚本中加载环境变量(适用于crontab)
  5. Python笔记-类装饰器
  6. RabbitMQ笔记-使用rabbitmq-c实现Fair dispatch(公平分发)
  7. java web认证考试_用Java实现Web服务器HTTP协议
  8. numpy 删除所有为_用Numpy和Pandas工具分析销售数据
  9. python魔术方法abstract_python学习之面向对象高级特性和魔术方法
  10. 饼图大小调整_这么漂亮的双层饼图,你会做吗?让你工作汇报更出彩!