300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 浏览器的同源策略与跨域

浏览器的同源策略与跨域

时间:2019-06-26 04:30:10

相关推荐

浏览器的同源策略与跨域

本文所有案例在本地址都可找到:/dancingZhou/sameOrigin/tree/dev

什么是同源策略

两个页面地址中的协议、域名和端口号一致,则表示同源。

例如该地址 和以下地址对比

同源策略的限制:

存储在浏览器中的数据,如localStroage、Cooke和IndexedDB不能通过脚本跨域访问

不能通过脚本操作不同域下的DOM

不能通过ajax请求不同域的数据

为什么要同源策略

设置同源限制主要是为了安全,如果没有同源限制存在浏览器中的Cookie等其他数据可以任意读取,不同域下DOM任意操作,Ajax任意请求的话如果浏览了恶意网站那么就会泄漏这些隐私数据。

Cookie一般用来保存登录状态。在登录一个银行网站后此时浏览器中就保存了登录的状态,同时浏览了恶意网站,这时Cookie的信息没有同源限制的话恶意网站就可以获取这些Cookie信息来达到不为人知的目的。

如果可以操作不同域下的DOM可以用如下方式完成盗取信息。在自己的网站上嵌入一个iframe地址设置成银行地址,然后让iframe全屏显示,当你一不小心上当了输入你账号密码,我就可以通过DOM操作获取到输入的信息。

Ajax的限制同Cookie,如果带上Cookie去跨域访问接口就可以通过程序的验证被认为身份是合法的。

既然瞥见危害一角自然要严加防范,限制非同源操作。

怎么规避同源策略

在看法一个网站的过程中有的数据并不在同一台服务器上这时怎么跨域调用就是一个很棘手的问题,可以通过以下几个方式来规避同源的限制。

DOM同源策略的规避

hash

因为hash的改变并不会引起页面的刷新同时可以通过window.onhashchange事件监听到hash的改变,所以可以通过hash来跨域传递数据。

<!-- /index.html --><html><head><meta charset="utf8"/><title>跨域DEMO --- hash</title></head><body><iframe id="iframe" src="/index.html"></iframe><script>var ifra = document.getElementById('iframe');ifra.onload = function(){// ifra 加载完成了ifra.src = ifra.src + '#data';}</script></body></html>

<!-- /index.html --><!-- 在iframe中的页面()如果和iframe所在页面()不同域是不能获取所在页面的DOM,然后通过hash将数据传递回去的,也就是说如果同域就可以通过该方法向所在页面传递数据 --><html><head><meta charset="utf8"/><title>跨域DEMO --- hash</title></head><body><script>window.onhashchange = function(){// 打印通过hash传过来的数据console.log( location.hash ); }</script></body></html>

该方法会直接暴露所传递的数据并且对所传数据有大小限制。

document.domain

若两个文档的域相同则可以获取对方的DOM对象,并且可以通过设置 document.domain 的值来让两个文档的域保持一致,但是 document.domain 并不是可以设置任何值,只能设置为当前域的超域,比如:

设置为 ,并且不能 设置为 也不能将 设置为 。

所以document.domain只可以在拥有相同的主域名的不同子域名之间跨域。

<!----><html><head><meta charset="utf8"/><title>跨域DEMO --- document.domain</title></head><body><p id="data">我在 下</p><iframe id="ifra" src="/index.html"></iframe><script>// 这里为什么也要设置呢?因为document.domain的赋值会导致端口被覆盖成null,并且js中没有手段单独设置端口,所以这里设置一遍这样就和iframe中的一致了。document.domain = '';var ifra = document.getElementById('ifra');ifra.onload = function(){console.log( ifra.contentWindow.document.getElementById('data').innerHTML ); // 我是下的}</script></body></html>

<!----><html><head><meta charset="utf8"/><title>跨域DEMO --- document.domain</title></head><body><p id="data">我是下的</p><script>document.domain = '';console.log( parent.document.getElementById('data').innerHTML ); // 我在 下</script></body></html>

window.name

window.name有一个特性,即使当前窗口的地址改变了window.name的值也不会改变。可以利用这一特性来进行跨域,步骤如下:

通过iframe加载需要获取数据的地址在加载的文件上将数据设置到window.name上数据获取完成后将iframe的地址设置为当前文档同域通过DOM操作拿到window.name上的数据

<!----><html><head><meta charset="utf8"/><title>跨域DEMO --- window.name</title></head><body><iframe id="ifra" src="/index.html"></iframe><script>var retData = false;var ifra = document.getElementById('ifra');ifra.onload = function(){if( !retData ){ifra.src = '/index.html'retData = true;}else{console.log( ifra.contentWindow.name ); // 我在下}}</script></body></html>

<!----><html><head><meta charset="utf8"/><title>跨域DEMO --- window.name</title></head><body><script>window.name = '我在下';</script></body></html>

window.postMessage

以上几种跨域的方法都属于破解行为,而postMessage是H5为跨域提供的解决方法。

otherWindow.postMessage(message, targetOrigin[, transfer])

<!----><html><head><meta charset="utf8"/><title>跨域DEMO --- window.postMessage</title></head><body><iframe id="ifra" src="/index.html"/><script>var ifra = document.getElementById('ifra');ifra.onload = function(){ifra.contentWindow.postMessage('我来自', '')}</script></body></html>

<!----><html><head><meta charset="utf8"/><title>跨域DEMO --- window.postMessage</title></head><body><iframe src="/index.html"/><script>window.addEventListener('message', function(messageEvent){console.log( messageEvent.data ); // 我来自}, false)</script></body></html>

messageEvent对象上的属性中有三个属性要注意,分别是:

source 发送消息的窗体origin 发送消息的域名 (根据域名判断是否处理该消息)data 发送消息的内容 (获取发送的消息内容)

Ajax同源策略的规避

jsonp

虽然跨域限制了Ajax请求,但是却并不影响跨域引用脚本。

<script>function callback (data) {console.log(data); // 上面的加载完成之后就会打印出后台传过来的数据 "数据"} </script><script src="/index.php?arg=val1&jsonp=callback"></script>

<?phpecho $_GET['jsonp'] . '(' . '数据' . ')';?>

上面的 index.php 接口返回的是一段调用 函数的js代码 callback(data),其中data就是接口要返回的数据。而这个callback是事先在页面上写好的处理数据的回调函数,并且回调函数的名称通过URL参数的形式传递给了后端接口,这样就完成了一次跨域。

注:jsonp只支持GET请求。

CORS

cors(跨域资源共享)

参考

/zh-CN/docs/Web/Security/Same-origin_policy/zh-CN/docs/Web/API/Window/postMessage/blog//04/same-origin-policy.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。