IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 同源策略保护了什么、如何规避同源限制 -> 正文阅读

[网络协议]同源策略保护了什么、如何规避同源限制

同源策略保护了什么、如何规避同源限制

基本照抄阮一峰的博客:浏览器同源政策及其规避方法

同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它帮助阻隔恶意文档,减少可能被攻击的媒介。

例如cookie窃取,如果没有同源策略,当用户从网站a退出,进入另一个网站b时,网站b可能就拿到了用户在网站a中存储的cookie,泄露了用户的信息或伪装成用户向网站a的后端发送请求。

同源的要求:协议、域名、端口号相同

要求同源的场景:

如果不同源,以下三种行为会受到限制:

  • Cookie、localStorage、IndexDB 无法读取
  • DOM 无法获得
  • AJAX 请求不能发送

规避限制的方法

  1. cookie
    若两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置 document.domain共享Cookie
    举例:网页A:http://w1.example.com/a.html,网页B:http://w2.example.com/b.html
    只要A设置 document.domain = 'example.com'B就可以共享cookie,比如 即某子域名设置成一级域名,其余二级三级域名都可以共享这个子域名的cookie
    网页A设置一个cookie:document.cookie = 'test1=hello'
    网页B就可以读到这个cookie:var allCookie = document.cookie
    这种方法只适用于cookie和iframe窗口,localStorage和IndexDB无法通过这种方式规避同源策略,而是要使用PostMessage API。
    另外,服务器也可以在设置cookie的时候,指定cookie的所属域名为一级域名,比如 .example.com
    Set-Cookie: key=value; domain=.example.com; path=/
    这样的话,二级域名和三级域名不需要做任何设置,都可以读取这个cookie

  2. iframe

    1. 片段标识符

    2. window.name
      父窗口打开一个子窗口,载入一个不同源的网页,该网页将信息写入子窗口的 window.name属性中,子窗口跳转到一个和主窗口同源的网址:location = 'http://parent.url.com/xxx.html,然后主窗口读取子窗口的 window.name属性
      优点是:window.name容量很大,可以放置很长的字符串。
      缺点是:必须监听子窗口 window.name属性的变化,影响网页性能。

    3. window.postMessage HTML5新特性
      跨文档通信 API (Cross-document messaging)
      这个API为window对象添加了一个 window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。
      例如,父窗口 http://aaa.com向子窗口 http://bbb.com发送消息,调用 postMessage方法就可以了。

      var popup = window.open('http://bbb.com', 'title')
      popup.postMessage('Hello World!', 'http://bbb.com')
      

      该方法第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源,也可以设为 *表示不限制域名,向所有窗口发出

      子窗口向父窗口发送消息的写法类似:

      window.opener.postMessage('Nice to meet you', 'http://aaa.com')

      父窗口和子窗口都可以通过监听 message事件来获取对方的消息

      window.addEventListener('message', function (e) {
      	console.log()
      }, false)
      

      message事件的事件对象 event,提供以下三个属性。

      • event.source 发送消息的窗口
      • event.origin 消息所来自的网址
      • event.data 消息内容

      子窗口通过 event.source属性引用父窗口,然后发送消息。

      window.addEventListener('message', receiveMessage)
      function receiveMessage(event) {
      	event.source.postMessage('Nice to see you!', '*')
      }
      

      event.origin属性可以过滤不是发送给本窗口的消息

      window.addEventListener('message', receiveMessage)
      function receiveMessage(event) {
      	if (event.origin !== 'http://aaa.com') return;
      	if (event.data === 'Hello World') {
      		event.source.postMessage('Hello', event.origin)
      	} else {
      		console.log(event.data)
      	}
      }
      
    4. localStorage

      通过 window.postMessage,读写其他窗口的localStorage也成为了可能下面是一个主窗口写入iframe子窗口的localStorage的例子

      window.onmessage = function (e) {
      	if (e.origin !== 'http://bbb.com') {
         		return;
         	}
         	var payload = JSON.parse(e.target)
         	localStorage.setItem(payload.key, JSON.stringify(payload.data))
      }
      

      父窗口发送消息的代码如下:

      var win = document.getElementByTagName('iframe')[0].contentWindow;
      var obj = { name: 'Jack' }
      win.postMessage(JSON.stringify({key: 'storage', data: obj}), 'http://bbb.com')
      

      加强版的子窗口接收消息的代码如下:

      window.onmessage = function (e) {
      	if (e.origin !== 'http://bbb.com') return;
      	var payload = JSON.parse(e.target)
      	switch (payload.method) {
      		case 'set':
      			localStorage.setItem(payload.key, JSON.stringify(payload.data));
      			break;
      		case 'get':
      			var parent = window.parent
      			var data = localStorage.getItem(payload.key)
      			parent.postMessage(data, 'http://aaa.com')
      			break;
      		case 'remove':
      			localStorage.removeItem(payload.key)
      			break;
      	}
      }
      

      加强版的父窗口发送消息代码如下:

      var win = document.getElementByTagName('iframe')[0].contentWindow;
      var obj = { name: 'Jack' };
      
      win.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://bbb.com');
      win.postMessage(JSON.stringify({key: 'storage', method: 'get'}), '*')
      window.onmessage = function (e) {
      	if (e.origin !== 'http://aaa.com') return;
      	console.log(JSON.parse(e.data).name)
      }
      

      基本思路为:

      父窗口打开一个子窗口,并返回出了一个窗口对象(可调用此api的也可能是一个其他窗口的引用),用这个窗口对象给这个子窗口自身发送一个消息,目标域填写子窗口的域

      子窗口获取到父窗口的引用(window.parent),然后用这个引用给父窗口自身发送消息,目标域填写父窗口的。

  3. AJAX规避跨域的三种方式(之后补充

    • JSONP
    • WebSocket
    • CORS
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 19:06:09  更:2022-03-30 19:09:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:30:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码