本文主要讲一下前端跨域问题的几种解决方案。现在我把它们分享给你,给你一个参考。来和边肖一起看看吧。
1.相应的策略如下:
统一资源定位器
解释
允许交流?
http://www.a.com/a.js
http://www.a.com/b.js
同一个域名下
允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下的不同文件夹
允许
http://www.a.com:8000/a.js
http://www.a.com/b.js
相同的域名,不同的端口
不允许
http://www.a.com/a.js
https://www.a.com/b.js
相同的域名,不同的协议
不允许
http://www.a.com/a.js
http://70.32.92.74/b.js
Ip对应于域名
不允许
http://www.a.com/a.js
http://script.a.com/b.js
主域是相同的,但是子域是不同的。
不允许
http://www.a.com/a.js
http://a.com/b.js
相同的域名,不同的二级域名(同上)
否(在这种情况下不允许访问cookie)
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同的域名
不允许
特别注意两点:
第一,如果“前台”对协议和端口引起的跨域问题无能为力,
其次,在跨域问题上,只通过“URL头”来识别域,而不去尝试判断同一个ip地址对应两个域还是两个域在同一个ip上。
“URL的头”指的是window . location . protocol window . location . host,也可以理解为“域、协议、端口必须匹配”。
2. 前端解决跨域问题
1 document.domain + iframe (只有在主域相同的时候才能使用该方法)
1)在www.a.com/a.html:
document . domain= a . com ;
var IFR=document . createelement( iframe );
IFR . src= http://www . script . a . com/b . html ;
ifr.display=none
document . body . appendchild(IFR);
ifr.onload=function(){
var doc=IFR . content document | | IFR . content window . document;
//这里操作doc,也就是b.html
ifr.onload=null
};
2)在www.script.a.com/b.html:
document . domain= a . com ;
2 动态创建script
这个没什么好说的,因为脚本标签不受同源策略的限制。
函数loadScript(url,func) {
var head=document . head | | document . getelementbytagname( head )[0];
var script=document . createelement( script );
script.src=url
script . onl oad=script . onreadystatechange=function(){
如果(!this . ready state | | this . ready state== loaded | | this . ready state== complete ){
func();
script . onl oad=script . onreadystatechange=null;
}
};
head.insertBefore(脚本,0);
}
window.baidu={
sug:函数(数据){
console.log(数据);
}
}
loadScript( http://suggestion . Baidu . com/su?wd=w ,function(){ console . log( loaded )});
//我们请求的内容在哪里?
//我们可以在chorme调试面板的源码中看到脚本引入的内容。
3 location.hash + iframe
原理是使用location.hash来传递值。
假设域名为a.com的文件cs1.html想要与域名为cnblogs.com的cs2.html交流信息。
1)cs1.html首先自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面。
2)在cs2.html响应请求后,它将通过修改cs1.html的哈希值来传递数据。
3)同时在cs1.html中加入一个定时器,每隔一段时间判断location.hash的值是否有变化,一旦有变化,就获取hash值。
注意:由于两个页面不在同一个域中,IE和Chrome不允许修改parent.location.hash的值,所以我们不得不求助于a.com域名下的代理iframe。
代码如下:
第一,a.com下的文件,cs1.html文件:
函数startRequest(){
var IFR=document . createelement( iframe );
IFR . style . display= none ;
IFR . src= http://www . cn blogs . com/lab/cscript/cs2 . html # paramdo ;
document . body . appendchild(IFR);
}
函数checkHash() {
尝试{
var data=location.hash?location . hash . substring(1):“”;
if (console.log) {
console.log(现在数据是数据);
}
} catch(e){ };
}
setInterval(checkHash,2000);
cnblogs.com域名下的Cs2.html:
//模拟一个简单的参数处理操作
开关(location.hash){
案例#paramdo :
回调();
打破;
案例#paramset :
//做点什么……
打破;
}
函数回调(){
尝试{
父母。位置。hash=一些数据;
} catch (e) {
//ie、chrome的安全机制无法修改parent.location.hash,
//所以要利用一个中间的cnblogs域下的代理内联框架
var IFR proxy=文档。createelement(“iframe”);
IFR代理。风格。display= none
IFR代理。src= http://a . com/test/cscript/CS3。html # somedata ;//注意该文件在a.com的域下
文档。身体。appendchild(IFR代理);
}
}
a.com下的域名cs3.html
//因为父母父母和自身属于同一个域,所以可以改变其位置。哈希的值
父母。父母。位置。哈希=自我。位置。哈希。子串(1);
4 window.name + iframe
窗口。名称的美妙之处:名称值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的名字值(2MB)。
1) 创建a.com/cs1.html
2) 创建a.com/proxy.html,并加入如下代码
头
脚本
函数代理(url,func){
var isFirst=true,
IFR=文件createelement(“iframe”),
loadFunc=function(){
if(isFirst){
IFR。内容窗口。地点=http://a.com/cs1.html;
isFirst=false
}否则{
func(IFR。内容窗口。姓名);
ifr.contentWindow.close().
文档。身体。移除子项(IFR);
IFR。src=
ifr=null
}
};
ifr.src=url
IFR。风格。display= none
如果(IFR。附加事件)IFR。附加事件(“onload”,load func);
else ifr.onload=loadFunc
文档。身体。appendchild(iframe);
}
/脚本
/头
身体
脚本
代理(‘http://www.baidu.com/,函数(数据){
console.log(数据);
});
/脚本
/body
3在b.com/cs1.html中包含:
脚本
window.name=要传送的内容;
/脚本
5 postMessage(HTML5中的XMLHttpRequest Level 2中的API)
1)a.com/index.html中的代码:
iframe id= IFR src= b . com/index。html /iframe
脚本类型=文本/javascript
window.onload=function() {
var IFR=文档。getelementbyid( IFR );
var target origin= http://b . com//若写成http://b.com/c/proxy.html的效果一样
//若写成http://c.com的就不会执行邮件了
ifr.contentWindow.postMessage(我在那儿!,目标原点);
};
/脚本
2)b.com/index.html中的代码:
脚本类型=文本/javascript
窗户。addevent侦听器(消息,函数(事件){
//通过起源属性判断消息来源地址
如果(事件。origin== http://a . com ){
警报(事件。数据);//弹出"我在那里!"
警报(事件。来源);//对a.com、index.html中窗户对象的引用
//但由于同源策略,这里事件。来源不可以访问窗户对象
}
},假);
/脚本
6 CORS
克-奥二氏分级量表背后的思想,就是使用自定义的超文本传送协议头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
工业管理学(工业工程)中对克-奥二氏分级量表的实现是极速数据率
var XDR=new XDomainRequest();
xdr.onload=function(){
控制台。日志(XDR。responsetext);
}
xdr.open(get , http://www .百度一下。com’);
.
xdr.send(空);
其它浏览器中的实现就在xhr中
var xhr=new XMLHttpRequest();
xhr。onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr。状态=200 xhr。状态304 | | xhr。状态==304){
控制台。日志(xhr。responsetext);
}
}
}
xhr.open(get , http://www .百度一下。com’);
.
xhr.send(空);
实现跨浏览器的克-奥二氏分级量表
函数createCORS(方法,网址){
var xhr=new XMLHttpRequest();
if(xhr中的"带凭据"){
xhr.open(方法,网址,真);
}else if(typeof XDomainRequest!=未定义){
var xhr=new XDomainRequest();
xhr.open(方法,网址);
}否则{
xhr=null
}
返回xhr
}
var request=createCORS(get , http://www .百度一下。com’);
如果(请求){
request.onload=function(){
.
};
请求。send();
}
7 JSONP
JSONP包含两部分:回调函数和数据。
回调函数是当响应到来时要放在当前页面被调用的函数。
数据就是传入回调函数中的json数据,也就是回调函数的参数了。
函数handleResponse(响应){
console.log(响应的数据是: response . data );
}
var script=document . createelement( script );
script . src= http://www . Baidu . com/JSON/?callback=handle response ;
document . body . insert before(script,document . body . first child);
/* handleResonse({ data : zhe })*/
//原理如下:
//当我们通过脚本标签请求时
//后台会跟随相应的参数(json,handleResponse)
//生成相应的json数据(handle response({ data: zhe }))
//最后,这个返回的json数据(代码)会放在当前的js文件中执行。
//至此,跨域通信完成。
jsonp虽然很简单,但是有如下缺点:
1)安全问题(请求代码可能存在安全风险)
2)不容易确定jsonp请求是否失败。
8个网络插座
Web sockets是一个浏览器API,它的目标是在单个持久连接上提供全双工和双向通信。(同源策略不适用于web套接字)
WebSockets原理:JS创建web sockets后,会向浏览器发送一个HTTP请求来发起连接。得到服务器的响应后,建立的连接将使用HTTP upgrade从HTTP协议交换到web sockt协议。
它只能在支持web socket协议的服务器上工作。
var socket=new WebSockt( ws://www . Baidu . com );//http-ws;https-wss
socket . send( hello WebSockt );
socket . on message=function(event){
var data=event.data
}
原文链接:http://blog.csdn.net/joyhen/article/details/21631833
这就是本文的全部内容。希望对大家的学习有帮助,支持我们。