美文网首页
web安全、同源策略、跨域、 CORS之间的关系

web安全、同源策略、跨域、 CORS之间的关系

作者: 回调的幸福时光 | 来源:发表于2019-04-08 21:02 被阅读0次

前言

以往也了解过同源策略、跨域等方面的知识,但都是零零散散的,也没深入思考相互之间的联系,本文旨在通过将相关的知识点串联起来,系统性的归纳总结。

关系示意图.png

一、同源策略是什么?

同源策略限制了从同一个源加载的文档或脚本如何与来自另外一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

1.1 怎么才算是同源?

同时满足以下3个条件:

  1. 协议
    http 和 https 会被算作不同
  2. 域名
    注意二级域名和主域名会被算作不同
  3. 端口
1.2 同源策略具体限制了什么
  1. 无法读取非同源网页的 Cookie、LocalStorage、IndexedDB
  2. 无法接触非同源网页的 DOM
  3. 向非同源地址发送 AJAX 请求,浏览器会拦截请求的响应。

二、为什么要有同源策略?

试想一下,如果没有同源策略,会发生什么?
随便举几个例子,如果没有 1.2 中的种种限制,下面的情况很容易发生:

  1. 嵌套第三方网页,并修改第三方网页的 DOM 结构
  2. xss攻击难度降低
    在有同源策略之后,需要向被攻击站点注入脚本才能获取 LocalStorage、Cookie 中的信息,如果没有同源限制,只要被攻击者访问过其他站点,再访问攻击者的站点,攻击者站点中的脚本可直接获取被攻击者之前访问过的站点的信息了,都不需要注入脚本了。
  3. csrf 攻击
    既然能轻易获取到 cookie 等信息,可以直接通过 AJAX 发起伪造请求了。

通过以上 3 个例子可以看出,安全隐患太严重了,必须要引入同源策略来规避风险。

三、同源策略带来的问题

事物具有两面性,同源策略降低了安全风险的同时,也带来了很多不便。

再举几个例子:

  1. 前后端分离时期的 AJAX 跨域请求
  2. 新站点嵌套了部分旧站点页面,需要通信

不同源的站点或地址之间的通信被阻断,即常见的跨域问题

四、如何解决跨域

首先说明一点,跨域不仅仅包括 ajax 请求这一种情况,不同源的网页之间也有通信的需要。

(一) AJAX

4.1 JSONP

原理:

  1. <script> 标签的 src 属性是不受同源限制的(<img> 标签也是如此)
  2. 先提前定义好一个回调函数
function foo(data) {
  console.log(data);
}
  1. 将 foo 当做请求参数传递到服务器
  2. 服务器解析参数,获取 foo
  3. 服务器从数据库获取业务数据 data
  4. 服务器返回响应 foo(data) , 即把 data 当做参数
  5. 因为是通过 <script> 请求的,所以得到的响应就相当于请求回来一段 js 脚本,然后执行。

缺点:只支持 GET 请求。

4.2 CORS

CORS 全称是跨域资源共享(Cross-origin resource sharing)
详细请查看我的另一篇文章 CORS 学习笔记

4.3 Access-Control-Allow-Origin 白名单

其实就是 CORS 的具体实现。

服务端设置 header 头

Access-Control-Allow-Origin: *;

一般开发平台提供的 API 都是这样做的。但是对于不想开放的平台,使用 '*' 存在较大的安全风险,建议使用精确的域名来控制。

额外解答:为什么 Access-Control-Allow-Credentials: true; 时,不能设置 Access-Control-Allow-Origin 的值为 *
我的思考结论:Access-Control-Allow-Credentials 字段用来控制对带凭证的请求,服务器是否返回响应,Access-Control-Allow-Origin 字段用来控制请求的资源是否允许访问,我们先假设允许问题中的设置,会出现什么情况呢?会出现:一个携带凭证的跨域请求可以得到请求结果,猛一看好像没啥问题啊,我们平时开发不就为了实现跨域请求嘛,可是如果这个请求是伪造的呢?即 csrf 攻击,因为 Access-Control-Allow-Origin: * 所以同源策略中对于不同源 AJAX 请求的限制没了,这很容易造成安全问题。这里细心的同学会发现,那和 Access-Control-Allow-Credentials: true; 有什么关系呢?我的理解是,为什么请求需要带凭证呢,或者说什么样的请求需要带凭证?这样想就会明白,肯定是重要的资源,有安全要求,不想轻易被访问,所以服务器会对凭证进行校验,校验通过后才会返回响应的,因为像是开发平台这样的站点就是让别人请求的,所以设置Access-Control-Allow-Origin: *不会有问题,核心思想就是“重要的资源,不应该允许任意站点请求”,这个问题解释完了。

4.4 WebSocket

webSocket 是不受同源限制的。

4.5 代理服务器

浏览器请求同源服务器,服务器负责请求外部服务器。
举例:nginx 反向代理

(二) Cookie

4.6 设置 cookie 的 domain 属性

cookie 有个 domain 属性,用来设置 cookie 的作用域(结合 cookie 的另一个属性 path 使用)。

如果子域名 a.mozilla.org 和 b.mozilla.org 想要共享一段 cookie ,只要将 cookie 的 domain 属性设置成共同的父域名 domain=mozilla.org 即可。

4.7 document.domain

这里阮一峰的方法是在两个子站点中通过脚本设置 document.domain='mozilla.org'

缺点:

  • 不方便,因为需要协作的站点都要执行上述脚本才行,原因:document.domain = xxx会导致端口号被重置为null。
  • 不适合只需要共享部分 cookie 的需求

优点:document.domain 可以达到让父子域或者多个子域变成同源,作用不局限于 cookie 的共享。

(三) Iframe 跨窗口通信

4.8 片段识别符

指 url 中 # 后面的部分, 把需要传递的数据放到片段识别符中。

父窗口改变子窗口的片段标识符:

let src = originURL + '#' + data;
document.getElementById('childIFrame').src = src;

子窗口改变父窗口的片段标识符:

parent.location.href = target + '#' + hash;

监听 hash 的变化

window.onhashchange = function () {
  let msg = window.location.hash;
}

缺点:

  • url 长度有限,不能传递太多的数据
  • 不是标准规范
4.9 window.postMessage()

跨文档通信 API(Cross-document messaging)为 window 对象提供了postMessage(),允许跨窗口通信,无论是否同源。

语法:otherWindow.postMessage(message, targetOrigin, [transfer]);

父窗口向子窗口发送消息:

let pop = window.open('http://bbb.com', 'title');
pop.postMessage('hello world', 'http://bbb.com');

子窗口向父窗口发送消息:

window.opener.postMessage('I received', 'http://aaa.com');

监听消息:

window.addEventListener('message', function(e) {
  console.log(e.data);
})
  • event.source:发送消息的窗口
  • event.origin: 消息发向的网址
  • event.data: 消息内容

安全

  • 不希望从其他网站接收 message,请不要为 message 添加事件监听。
  • 始终使用 originsource 属性验证发件人的身份。
  • 向其他窗口发送数据时,指定精确的 origin

参考

阮一峰:同源策略
阮一峰:CORS
会编程的银猪:同源策略和跨域请求研究
MDN:Same-origin_policy
MDN:postMessage
MDN:CORSNotSupportingCredentials
MDN:Access-Control-Allow-Credentials

相关文章

  • web安全、同源策略、跨域、 CORS之间的关系

    前言 以往也了解过同源策略、跨域等方面的知识,但都是零零散散的,也没深入思考相互之间的联系,本文旨在通过将相关的知...

  • Spring Boot中通过CORS解决跨域问题

    Spring Boot中通过CORS解决跨域问题 同源策略 同源策略是由Netscape提出的一个著名的安全策略,...

  • 跨域

    主要内容: 同源策略、跨域实现形式(JSONP、CORS、降域、postMessage) 同源策略 (Same o...

  • SpringBoot2.x整合CORS解决跨域问题

    跨域问题系列文章 1. 同源策略与CORS(跨域请求的起源)2. SpringBoot2.x整合CORS解决跨域问...

  • 什么是跨域?跨域有几种实现形式:

    跨域指的是跨过同源策略,实现不同域之间进行数据交互的过程叫跨域。跨域的实现形式主要有JSONP方法、CORS方法、...

  • 跨域

    跨域指的是跨过同源策略,实现不同域之间进行数据交互的过程叫跨域。跨域的实现形式主要有JSONP方法、CORS方法、...

  • 【WEB】浏览器同源策略及跨域资源共享(CORS)

    本文主要参考跨域资源共享 CORS 详解 浏览器的同源策略一直以来都是Web安全的基础,但这同时也制约了Web研发...

  • 同源策略与跨域

    跨域就是违背了同源策略解决跨域的方法有:jsonp,cors和服务器代理

  • 前端跨域的整理

    跨域资源共享 CORS 对于web开发来讲,由于浏览器的同源策略,我们需要经常使用一些hack的方法去跨域获取资源...

  • AJAX入门

    处理跨域的主要方法 JSONP CORS本文主要讨论CORS解决AJAX因为浏览器同源策略不能跨域请求数据的问题。...

网友评论

      本文标题:web安全、同源策略、跨域、 CORS之间的关系

      本文链接:https://www.haomeiwen.com/subject/mfnqiqtx.html