博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
也谈跨域数据交互解决方案
阅读量:5895 次
发布时间:2019-06-19

本文共 2748 字,大约阅读时间需要 9 分钟。

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

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

JSONP

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

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

<
script
type
=
"text/javascript"
src
=
"()"
></
script
>
<
script
type
=
"text/javascript"
>
    
alert(ACD.responseText);
</
script
>
<
script
type
=
"text/javascript"
src
=
"()&method=post&postdata=(name=fred&email=fred@fred.com)"
></
script
>
<
script
type
=
"text/javascript"
>
    
alert(ACD.responseText);
</
script
>

实际上这个方案是借助后端把,后端根据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几乎一模一样:

var
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'
,
''
);
  
req.send();
}

Iframe+XMLHttpRequest

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

var
req =
new
XDR();
req.open(
"POST"
,
""
);
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,它是一个数组,支持用正则定义允许交互的站点。

终极解决方案:Cross-Origin Resource Sharing

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

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

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

总结

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

转载地址:http://ewisx.baihongyu.com/

你可能感兴趣的文章
JVM的总结
查看>>
Linux内核堆栈使用方法 进程0和进程1【转】
查看>>
有了GPRS为什么还要LoRa和NB-IoT?【转】
查看>>
Linux USB驱动框架分析【转】
查看>>
ES6中export , export default , import模块系统总结
查看>>
禁止微信下拉到顶部时露底--代码记录
查看>>
html包含的属性设置
查看>>
【Alpha】项目展示
查看>>
树上倍增求LCA
查看>>
C#扩展一般用于linq
查看>>
UVA 11478(差分约束 + 二分)
查看>>
mysql.user表中Host为%的含义
查看>>
python 变量作用域
查看>>
算法复杂性为O (n2)
查看>>
磁盘挂载自动分区脚本
查看>>
C博客作业01--分支、顺序结构
查看>>
Servlet的说明及使用案例
查看>>
css
查看>>
二极管测试
查看>>
PHP跳转页面的几种实现方法详解
查看>>