跨域方法
Published by Shangyu Liu,
首先要明确,跨域的两方都是在自己的掌握之下的,跨域获取不相干的别人的数据是不可能的!
同源策略:协议(http、https是不同协议)、子域名、主域名、端口,任何一个不同,都是跨域,没有请求权限
1、iframe跨域
1)利用hash:对于iframe不可修改父窗口hash的情况,需要三个页面,a内嵌b(跨域页面),b内嵌c,b在内嵌c的时候,把数据添加到c地址的锚点,c与a同域,c内修改a的hash(parent.parent.location.hash),如果跨域的b可以修改a的hash(firefox),直接修改就好了。遗憾的是没有直接监听hashchange事件的方法,需要setInterval来查询。
2)利用window.name:window.name有两个好的属性,一是同一个window下跳转不变,二是存储的数据量比较大(2M),所以可以内嵌一个iframe,先载入跨域页面,监听onload,跨域页面中为window.name赋值,onload调用时载入完成,修改location跳转到本域的空iframe(window.name不变)此时iframe与父页面同域,可以在在主页面通过contentWindow.name获取传递数据。
3)domain子域传递:此方法只能在同一个基础域下父域与子域或子域之间传递信息,同样是用iframe内嵌,只不过在两个页面设置domain为相同的父域而已(domain该怎么设置是清楚的,必须是父域或自己,父域也不可能直接搞成com这种顶级域名啊!)
4)postMessage:同样利用iframe,在iframe上面调用contentWindow.postMessage(data,target),在iframe上绑定message事件,等到数据传过来处理就好了,target是指可跨域的目标,"*"就是全部可跨域,当然iframe向父页面传递,自然是window.postMessage就可以了
2、jsonp跨域
利用了同源策略的一个小漏洞,在同源策略中,所有含有src属性的标签,都可以请求非同源的数据,显然img是这么干的,那么jsonp的原理就非常的简单了,在本地创建一个script标签,标签内引用非同源的js就可以了。
经过测试发现,在script标签里引用的文件无论是否为js后缀都是没问题的,只要里面是一串在script里面可以运行的字符串就可以了,因此这个就好办了,把js标签动态的创建,src指向跨域的php或其他后端代码,记住,同源策略保护的是本域的代码,所以跨域发送的请求,对方是妥妥可以收到的,而对方返回的字符串在script中,所以是可以运行的,这样,只需要将callback的名称、参数放在请求地址的hash部分,就可以动态在跨域的web端创建调用代码了,一旦字符串返回,调用就开始了,注意,这里jsonp必须用get方法,在调用过程中,callback的实参是json格式的,方便数据处理,故名jsonp(package),记住口诀,本地定义、远程调用,而远程调用的目的是为了将有效数据一股脑全部塞入这个callback的实参中,所以看返回的内容,函数体很小,大部分内容是callback的一个json格式的大大的实参。
显然这种方法也是异步的,但是跟ajax不是一个概念,callback拿到数据如何处理呢,最简单的办法就是在callback中把json给外部变量了,更好的方法再思考。
3、xhr2跨域
html5,支持了xhr的跨域请求,客户端与之前没什么区别,仅需要在服务端返回http请求的时候设置下header中的首部字段:Access-Controll-Allow-Origin,Access-Controll-Allow-Method,前者设置跨域url(可以像postMessage那样设置为全部),后者设置可跨域的方法。
4、后端代理
利用后端的代码完成不同域名下的数据传递,这是更标准的方法了,原理上很好理解(代码实现,挖坑待填)