MENU

1994世界杯_1954年世界杯 - hengshuifu.com

什么是跨域?跨域产生原因与解决方法

一、什么是跨域?

当一个请求url的协议、域名、端口三者之间的任意一个与当前页面url不同即为跨域。

当前页面url

被请求页面url

是否跨域

原因

http://www.test.com/

http://www.test.com/index.html

同源(协议、域名、端口号相同)

http://www.test.com/

https://www.test.com/index.html

跨域

协议不同(http/https)

http://www.test.com/

http://www.baidu.com/

跨域

主域名不同(test/baidu)

http://www.test.com/

http://blog.test.com/

跨域

子域名不同(www/blog)

http://www.test.com:8080/

http://www.test.com:7001/

跨域

端口号不同(8080/7001)

二、为什么会出现跨域?

出于浏览器的*同源策略限制**。

同源策略(Same Orgin Policy)是一种约定,它是浏览器核心也最基本的安全功能,它会阻止一个域的js脚本和另外一个域的内容进行交互,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。。所谓同源(即在同一个域)就是两个页面具有相同的协议(protocol)、主机(host)和端口号(port)。

三、非同源限制

无法读取非同源网页的cookie、localstorage和indexedDB

无法接触非同源网页的DOM和js对象

无法向非同源地址发送Ajax请求

四、跨域解决方法

(1)document.domain + iframe跨域

(2)location.hash + iframe跨域

(3)window.name + iframe跨域

(4)postMessage跨域

(5)通过jsonp跨域

(6)跨域资源共享(CORS)

(7)Nginx反向代理

(8)nodejs中间件地代理跨域

(9)WebSocket协议跨域

一般来说,前三个是iframe的跨域;窗口之间JS跨域postMessage;简单的跨域请求jsonp即可,复杂的用cors;开发环境下接口跨域用nginx反向代理或node中间件比较方便。

4.1、document.domain + iframe跨域

该方法仅限于主域相同,子域不同的跨域应用场景。

实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

(1)父窗口:http://www.domain.com/a.html

(2)子窗口:http://child.domain.com/b.html

4.2、location.hash + iframe跨域

实现场景:A域(a.html)-> B域(b.html)-> A域(c.html)。a与b不同域只能单向通信,但c与a同域,所以c可以通过parent.parent访问a页面所有对象。

实现原理:三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

(1)a.html:http://www.domain1.com/a.html

(2)b.html:http://www.domain2.com/b.html

(3)c.html:(http://www.domain1.com/c.html)

4.3、window.name + iframe跨域

实现原理:通过iframe的src属性由外域转向本地域,跨域数据即由if让么的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时又是安全操作。

window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

(1)a.html:http://www.domain1.com/a.html

var proxy = function(url, callback) {

var state = 0;

var iframe = document.createElement('iframe');

// 加载跨域页面

iframe.src = url;

// onload事件会触发2次,第1次加载跨域页,并留存数据于window.name

iframe.onload = function() {

if (state === 1) {

// 第2次onload(同域proxy页)成功后,读取同域window.name中数据

callback(iframe.contentWindow.name);

destoryFrame();

} else if (state === 0) {

// 第1次onload(跨域页)成功后,切换到同域代理页面

iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';

state = 1;

}

};

document.body.appendChild(iframe);

// 获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)

function destoryFrame() {

iframe.contentWindow.document.write('');

iframe.contentWindow.close();

document.body.removeChild(iframe);

}

};

// 请求跨域b页面数据

proxy('http://www.domain2.com/b.html', function(data){

alert(data);

});

(2)proxy.html:http://www.domain1.com/proxy....

中间代理页,与a.html同域,内容为空即可。

(3)b.html:http://www.domain2.com/b.html

4.4、postMessage跨域

实现原理:postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可以用于解决以下方面的问题:

页面和其打开的新窗口的数据传递

多窗口之间的消息传递

页面与嵌套的iframe消息传递

上面三个场景的跨域数据传递

用法:postMessage(data,origin)方法接受两个参数

data:html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringfy()序列化。

origin:协议+主机+端口号,也可设置为‘*’,表示可以传递给任意窗口,如果要制定和当前窗口同源的话设置为‘/’。

(1)a.html:http://www.domain1.com/a.html

(2)b.html:http://www.domain2.com/b.html

4.5、通过jsonp跨域

实现原理:通常为了减轻web服务器的负载,我们把js、css、图片等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许。我们可以利用

Copyright © 2022 1994世界杯_1954年世界杯 - hengshuifu.com All Rights Reserved.