了解浏览器的一些安全策略同时了解跨域问题.
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:blank
或 javascript:
URL 执行的脚本会继承打开该 URL 的文档的源,因为这些类型的 URL 没有包含源服务器的相关信息。
例如,about:blank
通常作为父脚本写入内容的新的空白弹出窗口的 URL(例如,通过 Window.open()
)。如果此弹出窗口也包含 JavaScript,则该脚本将从创建它的脚本那里继承对应的源。
跨源网络访问
同源策略会影响不同源之间的交互.
例如在使用
XMLHttpRequest
或img
标签时则会受到同源策略的约束。这些交互通常分为三类:
- 跨源写操作(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
展示的图片。 - 通过
video
和audio
播放的多媒体资源。 - 通过
object
和embed
嵌入的插件。 - 通过
@font-face
引入的字体。一些浏览器允许跨源字体(cross-origin fonts),另一些需要同源字体(same-origin fonts)。 - 通过iframe载入的资源。站点可以使用
X-Frame-Options
标头来阻止这种形式的跨源交互。
这份跨源共享标准允许在下列场景中使用跨站点 HTTP 请求:
- 前文提到的由
XMLHttpRequest
或 Fetch API 发起的跨源 HTTP 请求。 - Web 字体(CSS 中通过
@font-face
使用跨源字体资源),因此,网站就可以发布 TrueType 字体资源,并只允许已授权网站进行跨站调用。 - WebGL 贴图。
- 使用
drawImage()
将图片或视频画面绘制到 canvas。 - 来自图像的 CSS 图形 (en-US)。
可以使用 CORS 来允许跨源访问。CORS 是 HTTP 的一部分,它允许服务端来指定哪些主机可以从这个服务端加载资源。
正题
cors是一种基于HTTP头的机制,解决浏览器同源策略,允许服务器标示除了它自己以外的其它源(域、协议或端口),使得浏览器允许这些源访问加载自己的资源.
CORS 标头
-
指示响应的资源是否可以被给定的来源共享。
Access-Control-Allow-Credentials
指示当请求的凭证标记为 true 时,是否可以公开对该请求响应。
-
用在对预检请求的响应中,指示实际的请求中可以使用哪些 HTTP 标头。
-
指定对预检请求的响应中,哪些 HTTP 方法允许访问请求的资源。
-
通过列出标头的名称,指示哪些标头可以作为响应的一部分公开。
-
指示预检请求的结果能被缓存多久。
Access-Control-Request-Headers
用于发起一个预检请求,告知服务器正式请求会使用哪些 HTTP 标头。
-
用于发起一个预检请求,告知服务器正式请求会使用哪一种 HTTP 请求方法。
-
指示获取资源的请求是从什么源发起的。
跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,通过浏览器发起一个到服务器托管的跨源资源的“预检”请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头.
实际访问控制场景
允许人为设置下面的字段
Content-Type
(需要注意额外的限制)Content-Type
标头所指定的媒体类型的值仅限于下列三者之一:text/plain
multipart/form-data
application/x-www-form-urlencoded
具体请查阅MDN跨源资源共享(CORS) - HTTP | MDN (mozilla.org)
如果 https://bar.other
的资源持有者想限制他的资源只能通过 https://foo.example
来访问,使用 Origin
和 Access-Control-Allow-Origin
就能完成最简单的访问控制
- 预检请求
使用 Origin
和 Access-Control-Allow-Origin
就能完成最简单的访问控制。如果 https://bar.other
的资源持有者想限制他的资源只能通过 https://foo.example
来访问
附带身份凭证的请求
一般而言,对于跨源
XMLHttpRequest
或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置XMLHttpRequest
对象的某个特殊标志位,或在构造Request
对象时设置1
2const 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
指令的对其进行配置,这也同样意味着脚本文件仅允许从原始服务器获取。