浏览器CORS和CSP介绍

了解浏览器的一些安全策略同时了解跨域问题.

CORS

全称是跨源资源共享(Cross-Origin Resource Sharing).是一个系统,它由一系列传输的 HTTP 标头组成,这些 HTTP 标头决定浏览器是否阻止前端 JavaScript 代码获取跨源请求的响应.

这又涉及到了浏览器的同源策略.

前置知识

同源策略是一个重要的安全策略,它用于限制一个的文档或者它加载的脚本如何能与另一个源的资源进行交互。

它能帮助阻隔恶意文档,减少可能被攻击的媒介。例如,它可以防止互联网上的恶意网站在浏览器中运行 JS 脚本,从第三方网络邮件服务(用户已登录)或公司内网(因没有公共 IP 地址而受到保护,不会被攻击者直接访问)读取数据,并将这些数据转发给攻击者。

源的定义

如果两个 URL 的协议端口 (en-US)(如果有指定的话)和主机都相同的话,则这两个 URL 是同源的。这个方案也被称为“协议/主机/端口元组”,或者直接是“元组”。(“元组”是指一组项目构成的整体,具有双重/三重/四重/五重等通用形式。)

协议比如http,https. 主机是域名或者ip地址.

URL结果原因
http://store.company.com/dir2/other.html同源只有路径不同
http://store.company.com/dir/inner/another.html同源只有路径不同
https://store.company.com/secure.html失败协议不同
http://store.company.com:81/dir/etc.html失败端口不同(http:// 默认端口是 80)
http://news.company.com/dir/other.html失败主机不同

除了一般的HTTP还有文件源.

现代浏览器通常将使用 file:/// 模式加载的文件的来源视为不透明的来源。这意味着,假如一个文件包括来自同一文件夹的其它文件,它们不会被认为来自同一来源,并可能引发 CORS 错误

源的继承

在页面中通过 about:blankjavascript: URL 执行的脚本会继承打开该 URL 的文档的源,因为这些类型的 URL 没有包含源服务器的相关信息。

例如,about:blank 通常作为父脚本写入内容的新的空白弹出窗口的 URL(例如,通过 Window.open())。如果此弹出窗口也包含 JavaScript,则该脚本将从创建它的脚本那里继承对应的源。

跨源网络访问

同源策略会影响不同源之间的交互.

例如在使用 XMLHttpRequestimg 标签时则会受到同源策略的约束。这些交互通常分为三类:

  • 跨源写操作(Cross-origin writes)一般是被允许的。例如链接、重定向以及表单提交。特定少数的 HTTP 请求需要添加预检请求
  • 跨源资源嵌入(Cross-origin embedding)一般是被允许的.
  • 跨源读操作(Cross-origin reads)一般是不被允许的,但常可以通过内嵌资源来巧妙的进行读取访问。例如,你可以读取嵌入图片的高度和宽度,调用内嵌脚本的方法,或得知内嵌资源的可用性

以下是可能嵌入跨源的资源的一些示例:

  • 使用 <script src="…"></script> 标签嵌入的 JavaScript 脚本。语法错误信息只能被同源脚本中捕捉到。
  • 使用 <link rel="stylesheet" href="…"> 标签嵌入的 CSS。由于 CSS 的松散的语法规则,CSS 的跨源需要一个设置正确的 Content-Type 标头。如果样式表是跨源的,且 MIME 类型不正确,资源不以有效的 CSS 结构开始,浏览器会阻止它的加载。
  • 通过 img 展示的图片。
  • 通过videoaudio播放的多媒体资源。
  • 通过 objectembed 嵌入的插件。
  • 通过 @font-face 引入的字体。一些浏览器允许跨源字体(cross-origin fonts),另一些需要同源字体(same-origin fonts)。
  • 通过iframe载入的资源。站点可以使用 X-Frame-Options 标头来阻止这种形式的跨源交互。

这份跨源共享标准允许在下列场景中使用跨站点 HTTP 请求:

可以使用 CORS 来允许跨源访问。CORS 是 HTTP 的一部分,它允许服务端来指定哪些主机可以从这个服务端加载资源。

正题

cors是一种基于HTTP头的机制,解决浏览器同源策略,允许服务器标示除了它自己以外的其它(域、协议或端口),使得浏览器允许这些源访问加载自己的资源.

CORS 标头

跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,通过浏览器发起一个到服务器托管的跨源资源的“预检”请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头.

实际访问控制场景

  1. 简单请求不会触发CORS预检请求.

    若满足所有下述条件,

​ 允许人为设置下面的字段

具体请查阅MDN跨源资源共享(CORS) - HTTP | MDN (mozilla.org)

如果 https://bar.other 的资源持有者想限制他的资源只能通过 https://foo.example 来访问,使用 OriginAccess-Control-Allow-Origin 就能完成最简单的访问控制

  1. 预检请求

使用 OriginAccess-Control-Allow-Origin 就能完成最简单的访问控制。如果 https://bar.other 的资源持有者想限制他的资源只能通过 https://foo.example 来访问

  1. 附带身份凭证的请求

    一般而言,对于跨源 XMLHttpRequestFetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 对象的某个特殊标志位,或在构造 Request 对象时设置

    1
    2
    const invocation = new XMLHttpRequest();
    invocation.withCredentials = true;

    如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true,浏览器将不会把响应内容返回给请求的发送者

内容安全策略(CSP)

内容安全策略CSP)是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本XSS)和数据注入攻击等。无论是数据盗取、网站内容污染还是恶意软件分发,这些攻击都是主要的手段。

为使 CSP 可用,你需要配置你的网络服务器返回 Content-Security-Policy HTTP 标头(有时你会看到 X-Content-Security-Policy 标头,但那是旧版本,并且你无须再如此指定它)。

除此之外,meta 元素也可以被用来配置该策略,例如

1
2
3
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; img-src https://*; child-src 'none';" />

示例 1

一个网站管理者想要所有内容均来自站点的同一个源(不包括其子域名)。

1
Content-Security-Policy: default-src 'self'

示例 2

一个网站管理者允许内容来自信任的域名及其子域名(域名不必须与 CSP 设置所在的域名相同)。

1
Content-Security-Policy: default-src 'self' *.trusted.com

示例 3

一个网站管理者允许网页应用的用户在他们自己的内容中包含来自任何源的图片,但是限制音频或视频需从信任的资源提供者,所有脚本必须从特定主机服务器获取可信的代码。

1
Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com

在这里,各种内容默认仅允许从文档所在的源获取,但存在如下例外:

  • 图片可以从任何地方加载 (注意“*”通配符)。
  • 多媒体文件仅允许从 media1.com 和 media2.com 加载(不允许从这些站点的子域名)。
  • 可运行脚本仅允许来自于 userscripts.example.com。

示例 4

一个线上银行网站的管理者想要确保网站的所有内容都要通过 SSL 方式获取,以避免攻击者窃听用户发出的请求。

1
Content-Security-Policy: default-src https://onlinebanking.jumbobank.com

该服务器仅允许通过 HTTPS 方式并仅从 onlinebanking.jumbobank.com 域名来访问文档。

示例 5

一个在线邮箱的管理者想要允许在邮件里包含 HTML,同样图片允许从任何地方加载,但不允许 JavaScript 或者其它潜在的危险内容(从任意位置加载)。

1
Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *

注意这个示例并未指定 script-src (en-US);在此 CSP 示例中,站点通过 default-src 指令的对其进行配置,这也同样意味着脚本文件仅允许从原始服务器获取。

相关资料

  1. 跨源资源共享(CORS) - HTTP | MDN (mozilla.org)
  2. 内容安全策略(CSP) - HTTP | MDN (mozilla.org)
  3. 禹神:一小时彻底搞懂跨域&解决方案_哔哩哔哩_bilibili
-------------本文结束感谢您的阅读-------------
感谢阅读.

欢迎关注我的其它发布渠道