为何须要“跨域隔离”才能得到强大的功能

做者:Eiji Kitamura & Domenic Denicola

翻译:疯狂的技术宅html

原文:https://web.dev/why-coop-coep/前端

未经容许严禁转载git

为何须要跨域隔离才能使用功能强大的功能,例如 SharedArrayBufferperformance.measureMemory() 和 JS Self-Profiling API。程序员

简介

本文解释了为何须要跨域隔离才能启用浏览器上的强大功能。github

关键术语:本文使用了许多类似的术语。为了使事情更清楚,先让咱们明确它们:web

背景

Web 是基于 same-origin policy 构建的:这是一种安全功能,它是用来限制文档和脚本如何与其余来源的资源进行交互的。该原则限制了网站访问跨域资源的方式。例如,来自 https://a.example 的文档被禁止访问 https://b.example 上托管的数据。面试

可是,在历史上同源政策有一些例外。任何网站均可以:json

  • 嵌入跨域iframe
  • 包含跨域资源,例如图像或脚本
  • 用 DOM 引用打开跨域弹出窗口

若是能够从头开始设计 Web,则这些异常将不存在。不幸的是,当 web 社区意识到严格的同源策略的优点时,web 已经开始依赖这些例外。segmentfault

这种松散的同源策略的安全反作用有两种方式进行修补。一种方法是经过引入称为跨域资源共享(CORS)的新协议,其目的是确保服务器容许共享具备给定来源的资源。另外一种方法是经过隐式删除对跨域资源的直接脚本访问,同时保留向后兼容性。这样的跨域资源称为“不透明”资源。这就是为何除非把 CORS 应用于图像,不然经过CanvasRenderingContext2D 操做跨域图像的像素会失败的缘由。跨域

全部这些策略决策都在同一个浏览上下文组中发生(browsing context group)。

image.png

长期以来,CORS 和不透明资源的结合就足够使浏览器安全了。尽管有时会发现一些极端状况(例如 JSON 漏洞)须要打补丁,但总的来讲,不容许直接读取跨域资源的原始字节的原则是成功的。

全部这些都经过 Spectre) 进行了更改,这使得加载到与代码同一的浏览上下文组中的任何数据都具备可读性。若是 evil.com 嵌入了跨域图像,则他们能够用 Spectre 攻击读取其像素数据,这使得依赖“不透明性”的保护无效。

image.png

在理想状况下,全部跨域请求都应由拥有资源的服务器明确审核。若是拥有资源的服务器未提供审查,则数据将永远不会进入攻击者的浏览上下文组,所以他们将不会收到 Spectre 攻击的影响。咱们称其为跨域隔离状态。这正是COOP + COEP的意义所在。

在跨域隔离状态下,发出请求的站点被认为不太危险,而且能够解锁强大的功能,例如 SharedArrayBuffer performance.measureMemory 和 JS Self-Profiling API,这些功能本来能够用于相似 Spectre 的攻击。它还防止修改 document.domain

跨域嵌入策略

跨域嵌入策略(COEP)阻止文档加载任何未明确授予文档许可权的跨域资源(使用CORP或CORS)。使用这个功能,你能够声明文档没法加载此类资源。

image.png

要激活此策略,须要添加如下 HTTP 头:

Cross-Origin-Embedder-Policy: require-corp

require-corp 关键字是 COEP 惟一接受的值。这将强制执行如下策略:文档只能从同一来源加载资源,或者显式被标记为可从另外一来源加载的资源。

为了从其余来源加载资源,须要支持跨域资源共享(CORS)或跨域资源策略(CORP)。

跨域资源共享

若是跨域资源支持跨域资源共享(CORS),则可使用 crossorigin 属性将其加载到你的网页上,而不会被 COEP 阻止。

<img src="https://third-party.example.com/image.jpg" crossorigin>

若是这个图片资源带有 CORS 标头,应该用 crossorigin 属性,以便将经过使用 CORS 模式获取资源的请求。除非设置了 CORS 标头,不然将会阻止图像加载。

一样,你能够经过 fetch() 方法获取跨域数据,只要服务器使用正确的 HTTP 头进行响应,就不须要特殊处理。

跨域资源策略

跨域资源策略(CORP))最初是做为一种选项被加入的,能够防止你的资源被其余域加载。在 COEP 的上下文中,CORP 能够指定谁能够加载资源的策略。

Cross-Origin-Resource-Policy 标头有三个可能的值:

Cross-Origin-Resource-Policy: same-site

标记为 same-site 的资源只能从相同站点加载。

Cross-Origin-Resource-Policy: same-origin

标有 same-origin 的资源只能从相同的来源加载。

Cross-Origin-Resource-Policy: cross-origin

被标记为 cross-origin 的资源能够被任何网站加载。 (这个值 与 COEP 一块儿添加到了 CORP 规范中。)

添加 COEP 标头后,将没法用 service worker 来绕过限制。若是文档受到 COEP 标头的保护,则在响应进入文档过程以前或在进入控制文档的 service worker 以前,将遵照策略。

跨域开放者策略

跨域开放者策略(COOP)容许你经过将其余文档放在不一样的浏览器上下文组中,确保将其与其余文档隔离开,这样它们就不能直接与顶层窗口进行交互。例如,若是带有 COOP 的文档打开一个弹出窗口,则其 window.opener 属性将为 null。一样,打开器引用的 .closed 属性将返回 true

image.png

Cross-Origin-Opener-Policy 标头有三个可能的值:

Cross-Origin-Opener-Policy: same-origin

标有 same-origin 的文档能够与标有 same-origin 的同源文件共享相同的浏览上下文组。

image.png

Cross-Origin-Opener-Policy: same-origin-allow-popups

带有 same-origin-allow-popups 的顶级文档保留了对未设置 COOP 或经过把 COOP 设置为 unsafe-none 而选择退出隔离的任何弹出窗口的引用。

image.png

Cross-Origin-Opener-Policy: unsafe-none

unsafe-none 是默认设置,而且容许将文档添加到 opener 的浏览上下文组中,除非 opener 自己的 COOP 为 same-originsame-origin-allow-popups

noopener 属性有与 COOP 相同的效果,不一样之处在于它只能工做从 opener 那边开始。 (当第三方打开窗口时,你不能取消它的关联。)经过执行诸如 window.open(url, '_blank', 'noopener') <a target="_blank" rel="noopener">, 之类的操做来附加 noopener 时,你能够故意将你的窗口与打开的窗口解除关联。

尽管 noopener 能够用 COOP 代替,可是当你想在不支持 COOP 的浏览器中保护网站时,它仍然颇有用。

总结

若是要确保访问诸如 SharedArrayBufferPerformance.measureMemory 或 JS Self-Profiling API 之类的强大功能,只需记住你的文档须要同时使用 COEP (值为 require-corp )和 REOP(值为 same-origin)。

若是二者都不存在,浏览器将没法保证足够的隔离度以安全地启用那些强大的功能。你能够经过检查self.crossOriginIsolated 是否返回 true 来肯定页面的情况。

使用 COOP 和 COEP 使网站“跨域隔离” 一文中了解实现此步骤的步骤。

资源


本文首发微信公众号:前端先锋

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎继续阅读本专栏其它高赞文章:


相关文章
相关标签/搜索