所谓跨域,由于js在安全上面的考虑,只有同源的脚本间可以互相访问。哪些情况下构成跨域?
http://www.a.com和https://www.a.com http://www.a.com和http://www.a.com:80这两种分别由于协议号和端口号不同引起的跨域,暂时来说,js无能为力。
http://www.a.com http://70.32.92.74 域名和域名对应ip 也是无能为力。
下面讨论可以实现跨域的几种情况:
1 a.com 和 www.a.com 二级域名不同,设这document.domain = "a.com" 注意该方法只能设置一次,并且只能向更大的范围设置,即再想设置成
www.a.com是不可以的。用这种方法可以实现互相访问。
2 www.a.com 和 www.b.com 方法有如下几种:
A jsonp 可以轻松实现单向通信,详细的就不多说了,实现蛮简单的。
B 利用window.name实现单向通信,因为window.name不会随着url的变化而变化,在a中通过一个iframe指向b,请求的数据存在window.name里面,然
后修改改iframe指向a域名下,a就可以取到window.name了。
C 通过flash实现跨域。flash有自己的一套安全策略,服务器可以通过crossdomain.xml文件来声明能被哪些域的SWF文件访问,SWF也可以通过API来确定 自身能被哪些域的SWF加载。当跨域访问资源时,例如从域www.a.com请求域www.b.com上的数据,我们可以借助flash来发送HTTP请求。首先,修改 域www.b.com上的crossdomain.xml(一般存放在根目录,如果没有需要手动创建) ,把www.a.com加入到白名单。其次,通过Flash URLLoader发送 HTTP请求,最后,通过Flash API把响应结果传递给JavaScript。Flash URLLoader是一种很普遍的跨域解决方案,不过需要支持iOS的话,这个方案就无 能为力了。所以这个还得看个人的情况去适用。
D html5中有一个cros跨域方法,即 Access Control 必须在php中加入头信息。这是可以安全实现跨域的解决办法,可惜还没被所有浏览器支持。
E 设置代理服务器,让跨域问题到服务器端解决。
F FIM——Fragment Identitier Messaging 说白了就是由于iframe和父框架可以互相修改对方的url,所以把参数放在hash里面去,然后去获取。
对于父级框架,应该是 iframe[x].src = "xxx.com/html#hash"; iframe里面可以 parent.location.href = "xxxx.com/html2#hash" 此方法会产生大量url记录,而且还需要监控什么时候url获得变化,不赞成使用。
G window.postMessage
window.postMessage是HTML5定义的一个很新的方法,这个方法可以很方便地跨window通信。由于它是一个很新的方法,所以在很旧和比较旧的浏览器中都无法使用。
H Cross Frame
Cross Frame是FIM的一个变种,它借助了一个空白的iframe,不会产生多余的浏览器历史记录,也不需要轮询URL的改变,在可用性和性能上都做了很大的改观。它的基本原理大致是这样的,假设在域www.a.com上有页面A.html和一个空白代理页面proxyA.html, 另一个域www.b.com上有个页面B.html和一个空白代理页面proxyB.html,A.html需要向B.html中发送消息时,页面会创建一个隐藏的iframe, iframe的src指向proxyB.html并把message作为URL frag,由于B.html和proxyB.html是同域,所以在iframe加载完成之后,B.html可以获得iframe的URL,然后解析出 message,并移除该iframe。当B.html需要向A.html发送消息时,原理一样。Cross Frame是很好的双向通信方式,而且安全高效,但是它在Opera中无法使用,不过在Opera下面我们可以使用更简单的 window.postMessage来代替。
跨域方法总结:
跨域的方法很多,不同的应用场景我们都可以找到一个最合适的解决方案。比如单向的数据请求,我们应该优先选择JSONP或者window.name,双向通信我们采取Cross Frame,在未与数据提供方没有达成通信协议的情况下我们也可以用server proxy的方式来抓取数据。