本文主要介绍了js跨域实现的几种方法,并重点介绍了js跨域实现的五种方法。感兴趣的朋友可以参考一下。
从域说起
域:
域是WIN2K网络系统的安全边界。我们知道,计算机网络最基本的单位是“域”,它不是WIN2K独有的,但是active directory可以贯穿一个或多个域。在独立的计算机上,域是指计算机本身。一个域可以分布在多个物理位置,同时一个物理位置可以将不同的网段划分到不同的域中。每个域都有自己的安全策略以及与其他域的信任关系。当多个域通过信任关系连接时,Active Directory可以由多个信任域共享。域树:
域树由多个域组成,这些域共享相同的表结构和配置,形成一个连续的名称空间。树中的域通过信任关系连接,Active Directory包含一个或多个域树。树中的域由双向传递信任关系连接。因为这些信任关系是双向和可传递的,所以域树或林中新创建的域可以立即与域树或林中的所有其他域建立信任关系。这些信任关系允许单一登录过程对域树或林中所有域上的用户进行身份验证,但这并不一定意味着经过身份验证的用户在域树的所有域中具有相同的权利和权限。因为域是安全边界,所以必须在逐个域的基础上为用户分配相应的权利和权限。树中的域层次越深,级别越低,带有“.”代表一个等级。
例如,域名zhidao.baidu.com(百度知道)低于Baidu.com(百度),因为它有两个级别,而Baidu.com只有一个级别。
何为跨域
默认情况下,XHR对象只能访问包含它的页面所在的域中的资源。这种安全策略可以防止一些恶意行为。但是,合理的跨域请求的实现对于一些浏览器应用的开发也是至关重要的。
只要协议、域名、端口有任何不同,就视为不同的域。
例如,在http://www.a.com/a.js页面中,向下一个页面发送一个ajax请求。以下是请求的结果和描述。
端口和协议的差异只能在后台解决。我们需要解决的是域名不同的问题。
如何跨域
(一) CORS(Cross-Origin Resource Sharing,跨源资源共享)
1.CORS(跨源资源共享)是W3C的工作草案,它定义了当必须访问跨源资源时,浏览器和服务器应该如何通信。CORS背后的基本思想是使用自定义的HTTP头让浏览器与服务器通信,从而决定请求或响应应该成功还是失败。
2.实现这个功能很简单,只要服务器发送一个响应头就可以了。
浏览器支持:
IE 8
火狐3.5
歌剧12
Safari 4
铬3
假设我们的页面或应用程序已经在http://www.a.com/,我们打算请求从http://www.b.com提取数据。一般情况下,如果我们使用AJAX直接请求,会失败,浏览器会返回错误。
http://www.b.com只需在CORS添加一个报头,就可以允许来自http://www.a.com的请求。
下面的设置是用php做的。“*”符号表示允许任何域向我们的服务器提交请求:
标头{ Access-Control-Allow-Origin:* }
CORS的兼容写作
函数createCORSRequest(方法,url){
var xhr=new XMLHttpRequest();
//非IE浏览器
if(xhr中的“with credentials ”){
xhr.open(方法,url,true);
//IE浏览器
} else if (typeof XDomainRequest!=未定义){
vxhr=new XDomainRequest();
xhr.open(方法,URL);
}否则{
xhr=null
}
返回xhr
}
var request=createCORSRequest( get , http://www . something-else . com/page/);
如果(请求){
request.onload=function(){
//处理请求
};
request . send();
}
(二) JSONP(JSON with Padding 填充式JSON 或参数式JSON)
在js中,虽然我们不能直接使用XMLHttpRequest请求不同域的数据,但是可以在页面上引入不同域的js脚本文件。jsonp就是通过这个特性实现的。
JSONP由两部分组成:回调函数和数据。回调函数是响应到达时应该在页面中调用的函数,数据是传入回调函数的JSON数据。
例如:
脚本类型=文本/javascript
函数dosomething(jsondata){
//处理获取的json数据
}
/脚本
script src= http://example . com/data . PHP?callback=do something /脚本
首先,第一个脚本注释定义了一个处理数据的函数;
然后,第二个脚本标签加载一个js文件。http://example.com/data.php是数据的地址,但是因为是作为js引入的,所以http://example.com/data.php返回的一定是可执行的js文件;
最后,js文件加载成功后,会执行url参数中指定的函数,我们需要的json数据会作为参数传入。所以php应该是这样的
?服务器端编程语言(Professional Hypertext Preprocessor的缩写)
$ callback=$ _ GET[ callback ];//获取回调函数名
$data=array(a , b , c );//要返回的数据
echo $回调。(.json_encode($data)。);//输出
?
最后输出结果是:dosomething([a , b , c ]);
从上面可以看出,jsonp需要服务器端页面的相应配合。
JSONP的优缺点
优势:
它的兼容性更好,不需要XMLHttpRequest或ActiveX的支持,也可以在旧版浏览器上运行。
可以直接访问响应文本,支持浏览器和服务器双向通信。
缺点:
JSONP是从其他域加载代码的执行。如果其他域不安全,很可能会在响应中夹带一些恶意代码。这个时候除了彻底放弃JSONP调用之外,已经没有办法再追究了。所以在使用非自己操作的Web服务时,一定要确保安全可靠。
它只支持GET请求,不支持POST等其他类型的HTTP请求;只支持跨域HTTP请求,无法解决不同域的两个页面之间如何进行JavaScript调用的问题。
(三) window.name
window对象有一个name属性,它有一个特性:在一个窗口的生命周期内,该窗口加载的所有页面共享一个窗口。每个页面都有读写窗口的权限。window.name保存在窗口加载的所有页面中,不会因加载新页面而重置。
这里有三页:
A.com/app.html:申请页面。
A.com/proxy.html:代理文件,通常是没有任何内容的html文件,需要与应用程序页面在同一个域中。
B.com/data.html:应用页面需要获取数据,可以称为数据页面。
app.html
iframe src= b . com/data . html id= iframe /iframe
脚本
var iframe=document . getelementbyid( iframe );
iframe . src= a . com/proxy . html ;//这是一个与a.com/app.html.同源的页面
iframe.onload=function(){
var data=iframe . content window . name;//获取数据
}
/脚本
data.html
脚本
//这里是要传输的数据。大小一般是2M,但在IE和firefox下可以大到32M左右。
//可以自定义数据格式,比如json和string
Window.name= data
/脚本
Iframe的第一个地址是b.com/data.html,因此它可以获取window.name数据;
然而,iframe与app.html的来源不同,app.html无法获得数据,所以它将iframe的链接跳转到a.com/proxy.html.的代理页面,现在app.html和iframe是同一来源。
注意:iframe从b.com/data.html跳转到a.com/proxy.html页面,window.name的值不变。
获取数据后销毁iframe并释放内存;这也确保了安全性(不被其他域框架js访问)
脚本类型=文本/javascript
iframe . content window . document . write();
iframe . content window . close();
document . body . remove child(iframe);
/脚本
(四) document.domain + iframe
对于主域相同但子域不同的例子,可以通过设置document.domain来解决
具体做法是,分别在http://www.a.com/a.com和http://script.a.com/b.html文件中设置document.domain=a.com ,然后在a.html文件中创建一个iframe来控制iframe的contentDocument,这样两个js文件就可以“交互”了。
http://www.a.com/a.html佩奇
iframe src= http://script . a . com/b . html frame border= 0 /iframe
脚本
document . domain= a . com ;
/脚本
http://script.a.com/b.html佩奇
脚本
document . domain= a . com ;
/脚本
这样,两个页面可以通过js访问各种属性和对象。
document.domain的设置是有限制的
,我们只能将document.domain设置为自己或更高的父域,主域必须相同。比如a.b.example.com某个文档的document.domain可以设置为a.b.example.com、b.example.com、example.com中的任意一个,但是不能设置为c.a.b.example.com,因为是当前域的子域,也不能设置为Baidu.com,因为主域不一样。(五) HTML5的window.postMessage
window.postMessage (message,target origin)方法是html5新引入的特性。它可以用来向其他窗口对象发送消息,不管这个窗口对象属于同一个源还是不同的源。目前IE8、FireFox、Chrome、Opera等浏览器都已经支持window.postmessage方法。
Window.postMessage允许在两个窗口/框架之间跨域发送数据消息。本质上,window.postMessage是一个没有服务器pad的跨域Ajax。
用法:
other window . postmessage(message,target origin);
OtherWindow:对接收信息页的窗口的引用。可以是页面中iframe的contentWindow属性;窗口的返回值。开放;通过名称或下标从window.frames获取的值。
Message:要发送的数据,字符串类型。
TargetOrigin:用于限制otherWindow,“*”表示没有限制。
数据发送端
a.com/index.html:代码
iframe id= IFR src= b . com/index . html /iframe
脚本类型=文本/javascript
window.onload=function() {
var IFR=document . getelementbyid( IFR );
var target origin= http://b . com ;//设置接收方的域,*无限制。
ifr.contentWindow.postMessage(我在那儿!,target origin);
};
/脚本
数据接收端
b.com/index.html:代码
脚本类型=文本/javascript
window . addevent listener( message ,function(event){
//通过origin属性确定消息源地址。
if(event . origin== http://a . com ){
alert(event . data);//弹出‘我在那里!’
警报(event . source);//引用a.com和index.html的窗口对象
//但是因为同源策略,event.source无法访问这里的窗口对象。
}
},假);
/脚本
以上是js实现跨域的多种方式。希望对大家的学习有帮助。