前言
本文主要给大家介绍了关于web开发之跨域的解决方案,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
什么是跨域?
概念如下:只要协议、域名、端口有任何一个不同,都被当作是不同的域
下面是具体的跨域情况详解
URL
说明
是否允许通信
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
主域相同,子域不同
不允许(cookie这种情况下也不允许访问)
http://www.a.com/a.js、http://a.com/b.js
同一域名,不同二级域名(同上)
不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js、http://www.a.com/b.js
不同域名
不允许
一、document.domain跨域
原理:相同主域名不同子域名下的页面,可以设置document.domain
让它们同域
限制:同域document提供的是页面间的互操作,需要载入iframe页面
下面几个域名下的页面都是可以通过document.domain跨域互操作的: http://a.com/foo, http://b.a.com/bar, http://c.a.com/bar。 但只能以页面嵌套的方式来进行页面互操作,比如常见的iframe方式就可以完成页面嵌套
// URL http://a.com/foo var ifr = document.createElement('iframe'); ifr.src = 'http://b.a.com/bar'; ifr.onload = function(){ var ifrdoc = ifr.contentDocument || ifr.contentWindow.document; ifrdoc.getElementsById("foo").innerHTML); }; ifr.style.display = 'none'; document.body.appendChild(ifr);
上述代码所在的URL是http://a.com/foo,它对http://b.a.com/bar的DOM访问要求后者将 document.domain往上设置一级
// URL http://b.a.com/bar document.domain = 'a.com'
document.domain只能从子域设置到主域,往下设置以及往其他域名设置都是不允许的, 在Chrome中给出的错误是这样的
Uncaught DOMException: Failed to set the 'domain' property on 'Document': 'baidu.com' is not a suffix of 'b.a.com'
二、有src的标签
原理:所有具有src属性的HTML标签都是可以跨域的,包括<img>, <script>
限制:需要创建一个DOM对象,只能用于GET方法
在document.body
中append一个具有src属性的HTML标签, src属性值指向的URL会以GET方法被访问,该访问是可以跨域的
其实样式表的<link>标签也是可以跨域的,只要是有src或href的HTML标签都有跨域的能力
不同的HTML标签发送HTTP请求的时机不同,例如<img>在更改src属性时就会发送请求,而script, iframe, link[rel=stylesheet]
只有在添加到DOM树之后才会发送HTTP请求:
var img = new Image(); img.src = 'http://some/picture'; // 发送HTTP请求 var ifr = $('<iframe>', {src: 'http://b.a.com/bar'}); $('body').append(ifr); // 发送HTTP请求
三、JSONP
原理:<script>是可以跨域的,而且在跨域脚本中可以直接回调当前脚本的函数
限制:需要创建一个DOM对象并且添加到DOM树,只能用于GET方法
JSONP利用的是<script>可以跨域的特性,跨域URL返回的脚本不仅包含数据,还包含一个回调
// URL: http://b.a.com/foo var data = { foo: 'bar', bar: 'foo' }; callback(data);
然后在我们在主站http://a.com中,可以这样来跨域获取http://b.a.com的数据:
// URL: http://a.com/foo var callback = function(data){ // 处理跨域请求得到的数据 }; var script = $('<script>', {src: 'http://b.a.com/bar'}); $('body').append(script);
其实jQuery已经封装了JSONP的使用,我们可以这样来
$.getJSON( "http://b.a.com/bar?callback=callback", function( data ){ // 处理跨域请求得到的数据 });
$.getJSON与$.get的区别是前者会把responseText转换为JSON,而且当URL具有callback参数时, jQuery将会把它解释为一个JSONP请求,创建一个<script>标签来完成该请求
四、navigation 对象
原理:iframe之间是共享navigator对象的,用它来传递信息
要求:IE6/7
有些人注意到了IE6/7的一个漏洞:iframe之间的window.navigator
对象是共享的。 我们可以把它作为一个Messenger,通过它来传递信息。比如一个简单的委托:
// a.com navigation.onData(){ // 数据到达的处理函数 } typeof navigation.getData === 'function' || navigation.getData()
// b.com navigation.getData = function(){ $.get('/path/under/b.com') .success(function(data){ typeof navigation.onData === 'function' || navigation.onData(data) }); }
与document.navigator
类似,window.name
也是当前窗口所有页面所共享的。也可以用它来传递信息。 同样蛋疼的办法还有传递Hash(有些人叫锚点),这是因为每次浏览器打开一个URL时,URL后面的#xxx部分会保留下来,那么新的页面可以从这里获得上一个页面的数据
五、跨域资源共享(CORS)
原理:服务器设置Access-Control-Allow-OriginHTTP响应头之后,浏览器将会允许跨域请求
限制:浏览器需要支持HTML5,可以支持POST,PUT等方法
前面提到的跨域手段都是某种意义上的Hack, HTML5标准中提出的跨域资源共享(Cross Origin Resource Share,CORS)才是正道。 它支持其他的HTTP方法如PUT, POST等,可以从本质上解决跨域问题。
例如,从http://a.com要访问http://b.com的数据,通常情况下Chrome会因跨域请求而报错
XMLHttpRequest cannot load http://b.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.com' is therefore not allowed access
错误原因是被请求资源没有设置Access-Control-Allow-Origin,所以我们在b.com的服务器中设置这个响应头字段即可
Access-Control-Allow-Origin: * # 允许所有域名访问,或者 Access-Control-Allow-Origin: http://a.com # 只允许所有域名访问
六、window.postMessage
原理:HTML5允许窗口之间发送消息
限制:浏览器需要支持HTML5,获取窗口句柄后才能相互通信
这是一个安全的跨域通信方法,postMessage(message,targetOrigin)
也是HTML5引入的特性。 可以给任何一个window发送消息,不论是否同源。第二个参数可以是*但如果你设置了一个URL但不相符,那么该事件不会被分发。看一个普通的使用方式吧
// URL: http://a.com/foo var win = window.open('http://b.com/bar'); win.postMessage('Hello, bar!', 'http://b.com');
// URL: http://b.com/bar window.addEventListener('message',function(event) { console.log(event.data); });
七、访问控制安全的讨论
在HTML5之前,JSONP已经成为跨域的事实标准了,jQuery都给出了支持。 值得注意的是它只是Hack,并没有产生额外的安全问题。 因为JSONP要成功获取数据,需要跨域资源所在服务器的配合,比如资源所在服务器需要自愿地回调一个合适的函数,所以服务器仍然有能力控制资源的跨域访问
跨域的正道还是要使用HTML5提供的CORS头字段以及window.postMessage
, 可以支持POST, PUT等HTTP方法,从机制上解决跨域问题。 值得注意的是Access-Control-Allow-Origin头字段是资源所在服务器设置的, 访问控制的责任仍然是在提供资源的服务器一方,这和JSONP是一样的
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新日志
- 黑鸭子2010-再度重相逢[首版][WAV+CUE]
- 【原神手游】5.2版本圣遗物优化详情
- 方季惟.1989-一生只爱一次【蓝与白】【WAV+CUE】
- 群星.1997-强力舞曲总动员【金点】【WAV+CUE】
- 盘尼西林.2024-岛与黎明【智慧大狗】【FLAC分轨】
- 刀郎《柔情经典》 2CD[WAV分轨][3.8G]
- 群星2024《民谣精选》原音母版1:1直刻[低速原抓WAV+CUE][1.1G]
- 经典《泰坦尼克号原声大碟》[WAV+DSF+FLAC多版][5.2G]
- 魔兽世界兽王猎输出宏代码是什么 兽王猎翻页输出宏命令代码分享
- 魔兽世界wlk野德一键输出宏是什么 wlk野德一键输出宏介绍
- wlk鸟德一键输出宏是什么 wlk鸟德一键输出宏介绍
- 《明末:渊虚之羽》外网新宣传:有勇气面对障碍吗?
- 视觉盛宴!V社公布《看火人》团队新作水面物理效果演示
- 张艺谋呼吁观众走进影院看电影:对解说短视频很无语
- 车载音乐最强享受 《车载极致女声精选》[WAV分轨][1G]