跨域产生的原因 解决方案 原理

什么是跨域

当请求URL的协议、域名、端口号其中任意一个与当前页面url不同时,就是跨域。

为什么会发生跨域(同源策略)

浏览器具有同源策略,只有同源才能相互访问,不同源,则会发生跨域。
1、什么是同源?
同源就是同一个域,相同的协议、主机(域名)、端口号。

2、为什么要使用同源策略?
同源策略是浏览器最核心也是最基本的安全功能,它不允许一个域的js脚本与另一个域的脚本进行交互,有效防止XSS,CSRF等攻击。

3、同源策略造成的问题?
(1)无法读取不同源页面的cookie、localStorage和indexedDB(浏览器数据库)
(2)无法处理非同源的DOM元素与js对象
(3)无法向非同源页面发送ajax请求

跨域解决方案

1、document.domain+iframe
主域相同,子域不同,用js强制设置document.domain为基础主域,实现同域
例如:

父窗口: http://www.domain.com/a.html
子窗口:http://child.domain.com/b.html
在父页面中设置:
<script>
	document.domain = "domain.com";
	var user = "admin";
</script>
在子页面中设置:
<script>
	document.domain = "domain.com";
	console.log(window.parent.user);  //'admin'
</script>

2、location.hash+ifame
3个页面,不同域名之间传递数据
例如:

a.html: http://www.domain1.com/a.html
<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>
    var iframe = document.getElementById('iframe');

    // 向b.html传hash值
    setTimeout(function() {
        iframe.src = iframe.src + '#user=admin';
    }, 1000);
    
    // 开放给同域c.html的回调方法
    function onCallback(res) {
        alert('data from c.html ---> ' + res);
    }
</script>

b.html: http://www.domain2.com/b.html
<iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;"></iframe>
<script>
    var iframe = document.getElementById('iframe');

    // 监听a.html传来的hash值,再传给c.html
    window.onhashchange = function () {
        iframe.src = iframe.src + location.hash;
    };
</script>

c.html: http://www.domain1.com/c.html
<script>
    // 监听b.html传来的hash值
    window.onhashchange = function () {
        // 再通过操作同域a.html的js回调,将结果传回
        window.parent.parent.onCallback('hello: ' + location.hash.replace('#user=', ''));
    };
</script>

3、window.name+iframe
通过iframe的src属性,由外域转向本地域,跨域数据由window.name传递到本地域。name值在不同域加载后依然存在,而且支持很长的值,2M。
例如:

a.html: http://www.domain1.com/a.html
b.html: http://www.domain2.com/b.html
a请求b里面的window.name="This is domain2 data!";
a页面方法:
function proxy(url, callback){
	var state = 0;
	var iframe=document.createElement('iframe');
	iframe.src = url;
	iframe.onload = function(){
		if(state == 1){
			callback(iframe.contentWindow.name);
			//销毁
			destoryFrame();
		}else {
			//切换到同域
			iframe.contentWindow.location = "http://www.domain1.com/proxy.html";
			state = 1;
		}
	}
	document.body.append(iframe);
	function destoryFrame(){
		iframe.contentWindow.document.write('');
        iframe.contentWindow.close();
        document.body.removeChild(iframe);
	}
}

//请求数据
proxy("http://www.domain2.com/b.html", function(data){
	alert(data);
})
proxy.html是中间代理页面,与a同域,为空即可。

4、postMessage
页面和其打开的新窗口的数据传递
多窗口之间的消息传递
页面与嵌套的iframe消息传递
上面三个场景的跨域数据传递
例如:

a.html:http://www.domain1.com/a.html
iframe.contentWindow.postMessage(data, "http://www.domain2.com/b.html")
window.addEventListener('message', function(e){
	alert(e.data)
})

b.html:http://www.domain2.com/b.html
window.addEventListener('message', function(e){
	dataB = 'test'
})
window.parent.postMessage(dataB, "http://www.domain1.com/a.html");

5、jsonp
通常为了减轻服务器压力,会把js、css、图片等静态资源放到另一台独立域名的服务器上,在html中通过相应的标签从不同域名下加载静态资源,这种方式是被浏览器允许的。
所以可以让服务端返回一段调用某个函数的代码,在src中进行调用,实现跨域。
只能使用GET请求方式;需要后台封装数据
例如:

//在页面中动态定义script标签,传入调用的远程js文件
<script src="./getData.js"></script>
//远程getData.js文件返回一个含有调用函数名的数据
getremotedata({
    code:0,
    result:'success'
});

//使用jQuery发起jsonp请求
<script type="text/javascript">
    function GetAjaxData() {
        $.ajax({
            type: "get",
            async: false,
            url: "http://localhost:8080/getdata.php",
            dataType: "jsonp",
            jsonp: "callback",//传递给请求处理程序或页面的,标识jsonp回调函数名(一般为:callback)
            jsonpCallback: "GetData", //callback的function名称
            success: function (data) {
                console.log(data);
            },
            error: function () {
                alert('fail');
            }
        });
    }
</script>

6、跨域资源共享CORS
需要服务端实现CORS接口
对于简单请求,浏览器在头信息中添加也给Origin字段,添加远程域名,服务器根据这个值判断是否同意请求
CORS参考文章:http://www.ruanyifeng.com/blog/2016/04/cors.html
7、nginx反向代理
8、nodejs中间件代理跨域
9、WebSocket协议跨域

参考文章: http://www.manongjc.com/detail/19-vgapwneyijiifjt.html

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值