前端的需要掌握的知识储备要远远的大于实践
浏览器安全模型规定,XMLHttpRequest、框架(frame)等只能在一个域中通信。从安全角度考虑,这个规定很合理;但是,也确实给分布式(面向服务、混搭等等本周提到的概念)Web开发带来了麻烦。
所谓的跨域就是,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象
第一种:
window.name:就是window对象上的一个属性,只要窗口不发生变化(打开的不为_blank),这个值是一直存在,不会发生改变
a.com/app.html:
a.com/proxy.html:内容空白
b.com/data.html
需求:a.com/app.html需要访问b.com/data.html里面的数据
实现:在a.com/app.htm上加入一个iframe,然后src指向b.com/data.html,在b.com/data.html会执行一段脚本,将数据写入window.name上,这个时候a.com/app.html会执行iframe的onload函数将window.name读取进来,然后将src指向空白界面a.com/proxy.html
b.com/data.html
<script type="text/javascript"> window.name = 'I was there!'; </script>
a.com/app.html
<script type="text/javascript"> var state = 0, iframe = document.createElement('iframe'), loadfn = function() { if (state === 1) { var data = iframe.contentWindow.name; // 读取数据 alert(data); //弹出'I was there!' //删除iframe iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); } else if (state === 0) { state = 1; iframe.contentWindow.location = "http://a.com/proxy.html"; } }; iframe.src = 'http://b.com/data.html'; if (iframe.attachEvent) { iframe.attachEvent('onload', loadfn); } else { iframe.onload = loadfn; } document.body.appendChild(iframe); </script>
iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作
摘至:http://www.cnblogs.com/rainman/archive/2011/02/21/1960044.html
第二种:
iframe + location.hash : 利用location.hash来进行传值,http://a.com#helloword中的‘#helloworld’就是location.hash,最重要的是改变hash并不会导致页面刷新
需求:a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息
实现:cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面,这时的hash值可以做参数传递用。cs2.html响应请求后再将通过修改cs1.html的hash值来传递数据(由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值,所以要借助于a.com域名下的一个代理iframe;因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
而Firefox可以修改)。同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一点有变化则获取获取hash值。
a.com/cs1.html
function startRequest(){ var ifr = document.createElement('iframe'); ifr.style.display = 'none'; ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo'; document.body.appendChild(ifr); } function checkHash() { try { var data = location.hash ? location.hash.substring(1) : ''; if (console.log) { console.log('Now the data is '+data); } } catch(e) {}; } setInterval(checkHash, 2000);
cnblogs.com/cs2.html:
//模拟一个简单的参数处理操作 switch(location.hash){ case '#paramdo': callBack(); break; case '#paramset': //do something…… break; } function callBack(){ try { parent.location.hash = 'somedata'; } catch (e) { // ie、chrome的安全机制无法修改parent.location.hash, // 所以要利用一个中间的cnblogs域下的代理iframe var ifrproxy = document.createElement('iframe'); ifrproxy.style.display = 'none'; ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata'; // 注意该文件在"a.com"域下 document.body.appendChild(ifrproxy); } }
当然这样做也存在很多缺点,诸如数据直接暴露在了url中,数据容量和类型都有限等……
摘至:http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html
第三种:
window.opener:window的一个属性,它返回的是打开当前窗口的窗口对象,如果窗口A弹出一个窗口B,那么在B中window.opener就是窗口对象A
(友情提示:当你通过open打开了一个新窗口后,确保在新窗口中将opener属性设置为null(空).如果不这样的话,会使浏览器持续的保留每个opener的值,直至资源耗尽)
需求:建立1.htm,它用open方法打开2.htm,现在让2.htm给1.htm提供数据
原理:通过2.htm的opener来操控1.htm的location
1.htm
<script language="JavaScript"> window.open('2.htm', ', 'width=225,height=235,resizable=1,scrollbars=auto'); </script>
2.htm
<script language="JavaScript"> function ccc() { window.opener.document.bgColor='red'; } function xxx() { window.opener.document.location='http://angel1949.blogcn.co... } <input type="submit" name="Submit" value="变色" onClick="ccc()"> <input type="submit" name="Submit1" value="转向" onClick="xxx()">
这种方法适合弹出框跨域和window.parent的iframe跨域是完全不同的
摘至:http://blog.csdn.net/mpu/article/details/1375301
第四种:
JSONP:虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function
需求:a.html放问b.do数据
原理:在a.html动态创建一个script标签,向不同域的b.do发送请求,b.do返回一段js脚本在客户端立即执行,里面直接向回调函数注入数据
a.html
<script>
function callback(data){
alert("haha")
}
</script>
<script src="b.do?cb=callback"></script>
b.do服务器端返回
callback({name:"cc",age:"25"})
这样callback({name:"cc",age:"25"})会当做脚本直接在客户端执行,就实现了跨域请求数据的效果
JSONP 服务返回打包在函数调用中的 JSON 响应,而函数调用是由浏览器执行的,这使宿主 Web 应用程序更容易受到各类攻击。
第五种:
flash当跨域访问资源时,例如从域www.a.com请求域www.b.com上的数据,我们可以借助Flash来发送HTTP请求,不过对方域crossdomain.xml上要有授权
原理:使用URLLoader向目标域发一段请求,得到数据之后在通过ExternalInterface调用js的方法,将数据注入进去
代码略~~
第六种:
服务器代理,虽然浏览器的同源策略限制跨域请求,但在服务器端发送http请求就没有这限制了(比如说爬虫器)
原理:比如www.a.com要访问www.b.com里的数据,可以创建一个www.a.com/proxy代理,因为www.a.com和www.a.com/proxy是在同域不受限制,首先www.a.com会request给www.a.com/proxy,www.a.com/proxy会在服务器端向www.b.com发送请求,得到数据之后在response给www.a.com(用到了点长轮询的概念)
其他跨域方式:
Access Control
原理:请求的响应必须包含一个Access-Control-Allow-Origin的HTTP响应头,如:header("Access-Control-Allow-Origin: http://www.a.com");
局限:Firefox, Google Chrome等通过XMLHTTPRequest实现,IE8下通过XDomainRequest实现
document.domain
原理:将document的domain属性都修改为xx.com
局限:只能在子域之间通信
window.postMessage
原理:HTML5定义的一个很新的方法
局限:在很旧和比较旧的浏览器中都无法使用(ie6,7,8)
摘至:http://ued.koubei.com/?p=1291
6大类基本包括了绝大的部分,其他的就是根据项目量体裁衣了,欢迎其他高手补充~