浅谈跨域的几种方式

来源:互联网 发布:数据库系统课程设计 编辑:程序博客网 时间:2024/05/29 07:01

这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

跨域姿势小结

1、 最简单也最常见:使用jsonp ,即json with padding(内填充),顾名思义,就是把JSON填充到一个盒子里
2、 一劳永逸:直接在服务器端设置跨域资源访问 CORS(Cross-Origin Resource Sharing),设置Request Header头中Access-Control-Allow-Origin为指定可获取数据的域名
3、 找”爸爸”:通过修改document.domain来跨子域
4、 哥俩好:通过window.name来跨域接收数据
5、 新石器时代:使用HTML5的window.postMessage方法跨域

一、jsonp

核心思想:浏览器的script、img、iframe标签是不受同源策略限制的 ,所以通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的callback函数,并把把我们需要的json数据作为参数传入。在服务器端,当req.params参数中带有callback属性时,则把数据作为callback的参数执行,并拼接成一个字符串后返回。
- 优点:兼容性好,在很古老的浏览器中也可以用,简单易用,支持浏览器与服务器双向通信。
- 缺点:只支持GET请求,且只支持跨域HTTP请求这种情况(不支持HTTPS)

网页端的代码如下
这里写图片描述
创建一个函数tryJSONPadding,并在script标签的源地址中加入这个函数名,服务器端(Node.js写的后端)的处理如下
这里写图片描述

二、CORS

核心思想:在服务器端通过检查请求头部的origin,从而决定请求应该成功还是失败。具体的方法是在服务端设置Response Header响应头中的Access-Control-Allow-Origin为对应的域名,实现了CORS(跨域资源共享),这里出于在安全性方面的考虑就是尽量不要用 *,但对于一些不重要的数据则随意。下图是某公司阿里云服务器上的CORS设置
这里写图片描述

三、寻找相同主域document.domain

浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。有一点需要说明,不同的框架之间(父子或同辈),是能够获取到彼此的window对象的,但蛋疼的是你却不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外,还有些浏览器比如ie6也可以使用top、parent等少数几个属性),总之,你可以当做是只能获取到一个几乎无用的window对象。比如,有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:
这里写图片描述
这个时候,document.domain就可以派上用场了,我们只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。

在页面 http://www.example.com/a.html 中设置document.domain:
这里写图片描述
在页面 http://example.com/b.html 中也设置document.domain,而且这也是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值:
这里写图片描述
这样我们就可以通过js访问到iframe中的各种属性和对象了。

不过如果你想在http://www.example.com/a.html 页面中通过ajax直接请求http://example.com/b.html 页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同子域的框架间的交互。如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用一个隐藏的iframe来做一个代理。原理就是让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据的,然后就是通过我们刚刚讲得修改document.domain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发送ajax请求,然后收到的数据我们也可以获得了。

四、window.name

window对象中其实包含了黑魔法的,window.name属性就是其中之一,不同域的框架把想要共享的信息放在window.name里面,且此方法只适用于两个iframe之间的跨域。
这里写图片描述
1、在a.com网站添加一个空HTML页。名称为:http://a.com/null.html (用于实现二次跳转)
这里写图片描述
2、在a.com网站需要获取数据页面(如:http://a.com/getDomainData.html)
这里写图片描述
3、在b.com中添加获取数据页面 如:http://b.com/data.html 内容需包含:
这里写图片描述
接下来访问 http://a.com/getDomainData.html 就可返回 http://b.com/data.html 中的window.name中的数据了。

五、HTML5 中的window.postMessage方法

window.postMessage(message,targetOrigin) 方法是HTML5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。这种方法不能和服务端交换数据,只能在两个窗口(iframe)之间交换数据
www.example.com中主动发起连接
这里写图片描述
处于安全考虑,另一个域下的脚本中需要验证消息orgin来源后为http://www.example.com后再发送消息
这里写图片描述
event对象,这里的origin为http://localhost:81,仅作为演示
这里写图片描述

原创粉丝点击