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

什么是同源策略

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

例如该地址 https://www.google.com 和以下地址对比

地址 同源 原因
http://www.google.com 协议不一致
https://google.com 域名不一致
https://www.google.com:81 端口号不一致
https://www.google.com/a/s.html 协议,域名和端口号都一致

同源策略的限制:

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

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

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

为什么要同源策略

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

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

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

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

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

怎么规避同源策略

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

DOM同源策略的规避

hash

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

<!-- http://example.com/index.html -->
<html><head><meta charset="utf8"/><title>跨域DEMO --- hash</title></head><body><iframe id="iframe" src="http://example2.com/index.html"></iframe><script>var ifra = document.getElementById('iframe');ifra.onload = function(){// ifra 加载完成了ifra.src = ifra.src + '#data';}</script></body>
</html>
<!-- http://example2.com/index.html -->
<!-- 在iframe中的页面(example2.com)如果和iframe所在页面(example.com)不同域是不能获取所在页面的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 并不是可以设置任何值,只能设置为当前域的超域,比如:

m.example.com 设置为 example.com,并且不能 example.com 设置为 m.example.com 也不能将 m.example.com 设置为 example2.com。

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

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

window.name

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

  1. 通过iframe加载需要获取数据的地址
  2. 在加载的文件上将数据设置到window.name上
  3. 数据获取完成后将iframe的地址设置为当前文档同域
  4. 通过DOM操作拿到window.name上的数据
<!--http://example.com-->
<html><head><meta charset="utf8"/><title>跨域DEMO --- window.name</title></head><body><iframe id="ifra" src="http://example2.com/index.html"></iframe><script>var retData = false;var ifra = document.getElementById('ifra');ifra.onload = function(){if( !retData ){ifra.src = 'http://example.com/index.html'retData = true;}else{console.log( ifra.contentWindow.name ); // 我在example2.com下}}</script></body>
</html>
<!--http://example2.com-->
<html><head><meta charset="utf8"/><title>跨域DEMO --- window.name</title></head><body><script>window.name = '我在example2.com下';</script></body>
</html>

window.postMessage

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

otherWindow.postMessage(message, targetOrigin[, transfer])
<!--http://example.com-->
<html><head><meta charset="utf8"/><title>跨域DEMO --- window.postMessage</title></head><body><iframe id="ifra" src="http://example3.com/index.html"/><script>var ifra = document.getElementById('ifra');ifra.onload = function(){ifra.contentWindow.postMessage('我来自example.com', 'http://example3.com')}</script></body>
</html>
<!--http://example3.com-->
<html><head><meta charset="utf8"/><title>跨域DEMO --- window.postMessage</title></head><body><iframe src="http://example2.com/index.html"/><script>window.addEventListener('message', function(messageEvent){console.log( messageEvent.data ); // 我来自example.com}, false)</script></body>
</html>

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

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

Ajax同源策略的规避

jsonp

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

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

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

注:jsonp只支持GET请求。

CORS

cors(跨域资源共享)

参考

  1. https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy
  2. https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
  3. http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

浏览器的同源策略与跨域相关推荐

  1. 浏览器的同源策略与跨域问题的解决方案

    浏览器的同源策略与跨域问题的解决方案 参考文章: (1)浏览器的同源策略与跨域问题的解决方案 (2)https://www.cnblogs.com/yanggb/p/10735763.html 备忘一 ...

  2. 浏览器的同源策略及跨域解决方案

    同源策略 一个源的定义 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源. 举个例子: 下表给出了相对http://a.xyz.com/dir/page.html同源检测的示 ...

  3. 浏览器的同源策略和跨域请求_学习版

    目录 同源策略 : 跨域请求 : 跨域请求的常见解决方案 : 1. jsonp 2. cors(跨域资源共享) 3. proxy(代理) 同源策略 : 什么是同源策略 ? + 同源策略是  浏览器  ...

  4. 服务器安全:浏览器同源策略与跨域请求、XSS攻击原理及防御策略、如何防御CSRF攻击

    主要包括 浏览器同源策略与跨域请求 XSS攻击原理及防御策略 如何使用SpringSecurity防御CSRF攻击 CC/DDOS攻击与流量攻击 什么是SSL TLS HTTPS? 一.浏览器的同源策 ...

  5. 浏览器同源策略及跨域的解决方法

    浏览器同源策略及跨域的解决方法 参考文章: (1)浏览器同源策略及跨域的解决方法 (2)https://www.cnblogs.com/laixiangran/p/9064769.html 备忘一下.

  6. Django - - 进阶 - - 同源策略和跨域解决方案

    目录 同源策略 一个源的定义 同源策略是什么 举个例子 jQuery中getJSON方法 JSONP应用 1, 同源策略 1.1 一个源的定义 如果两个页面的协议,端口(如果有指定)和域名都相同,则两 ...

  7. websocket中发生数据丢失_tcp协议;websocket协议;同源策略和跨域

    tcp协议 为什么连接的时候是三次握手,关闭的时候却是四次握手? 答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文.其中ACK报文是用来应答的,SYN报 ...

  8. ajax背景、ajax对象、ajax状态、ajax与http、ajax请求数据接口、同步与异步、ajax请求XML数据、封装ajax函数、artTemplate简介、同源策略和跨域请求、JSONP

    AJAX简介: ajax背景: 1.AJAX(Asynchronous JavaScript And Xml)异步的 JavaScript 和 XML:ajax是浏览器提供的一套API,最早出现在谷歌 ...

  9. 同源策略和跨域解决方案

    同源策略 一个源的定义 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源. 举个例子: 下表给出了相对http://a.xyz.com/dir/page.html同源检测的示 ...

最新文章

  1. 表达式树 java_表达树—构建表达式树、获取表达式(二)
  2. Windows下Python 3.6 + VS2017 + Anaconda 解决Unable to find vcvarsall.bat问题
  3. 【存储知识学习】第六章-磁盘阵列-《大话存储》阅读笔记
  4. android 6.0 logcat机制(二)logcat从logd中获取log保存到文件中
  5. CoreOS上的Fleet,第二部分
  6. ANSYS——杆单元简介与示例(含新版本2019版本杆实常数设置、ANSYS help的使用、单元列表使用的举例)
  7. 一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
  8. 计算机视觉-SIFT
  9. Windows Phone 7 Developer Tools amp; Training Kit 正式版发布!
  10. a标签position为absolute时,IE无法点击(a position:absolute bug ie)
  11. C#LeetCode刷题之#532-数组中的K-diff数对(K-diff Pairs in an Array)
  12. 数据集蒸馏 by Matching Training Trajectories
  13. Python学习笔记(十三)文件操作函数
  14. CJOI 05新年好 (最短路+枚举)
  15. node.js的初步见解
  16. Iaas,paas,saas区别与联系
  17. c++编程求解二元二次方程组_二元一次方程组及其解法
  18. python包安装-centos7/windows
  19. OpenCasCade——将鼠标点的位置转换为基于OCC三维坐标系中在某一面上的坐标
  20. python音频识别_音频识别和比较

热门文章

  1. RabbiqMQ快速入门
  2. app store 关键词
  3. 三十七 Python分布式爬虫打造搜索引擎Scrapy精讲—将bloomfilter(布隆过滤器)集成到scrapy-redis中...
  4. JAVA记录-Servlet介绍
  5. 第2章 状态机思维与状态机变量
  6. jboss数据源配置
  7. Nodejs学习(三)-安装nodejs supervisor,提高点效率吧。
  8. eclipse加载maven工程提示pom.xml无法解析org.apache.maven.plugins:maven-resources-plugin:2.4.3解决方案...
  9. Shell基础学习(六) 流程控制
  10. 字符串字符和数字分割