Content Security Policy(CSP) 和 Cross-Origin Resource Sharing (CORS)

1 Content Security Policy

上周在工作中遇到了这样一个问题,在一个网页前端中,使用 Javascript 代码访问一个本地的服务,然后抛出了这样一个错误。

原本以为是服务端的错误,在 Google 之后才知道,这原来是 W3C 一个标准协议。那么究竟是怎么一回事呢?

我们都知道我们的网站会被会被一些不法分子攻击,比如跨站脚本(Cros是Site Script, XSS),比如说攻击者将一个脚本发送给其他人,由于同源策略,浏览器在执行这些脚本的时候,就能访问到被攻击者的敏感信息,然后将这些信息发送给攻击者。比如说

那么 Content Security Policy 是如何处理这个问题的呢?最直接的方法就是告诉浏览器不要执行访问 https://www.myserver.com 服务的操作,只有在白名单的中服务才能被访问。

Content Security Policy 可以采用两种方式完成

  1. 在请求返回的 Header 中添加一个 Content-Security-Policy 的 header

比如在 GitHub 页面的响应中,包含 content-security-policy 这样的 header

2. 第二种是在响应的页面中,为 head 元素增加一个 meta 记录

既然知道 Content-Security-Policy 的功能,那么如何自定义一个 Content-Security-Policy 呢?

Content-Security-Policy 的语法如下

每个 <policy-directive> 由两个部分组成,分别是 <directive> <value> ,比较常见的 directive

  • default-src: 当所有的其他规则都没有匹配上,才会进行 default-src 匹配计算
  • script-src: 所有 Javascript 脚本访问的服务的白名单
  • style-src: 所有 CSS 样式访问的服务资源
  • report-uri: 当如果有非白名单的资源访问的时候,向这个服务汇报情况

响应的 value 主要也有这些

  • none: 表示不允许访问任何外部资源
  • self: 可以访问 origin 下的资源
  • host: 具体的一个外部资源的地址,比如 example.com , https://*.example.com:12/path/to/file.js

最后我们看一个例子,以 twitter 举例

2. Cross-Origin Resource Sharing

通过 CSP, 浏览器可以在调用端限制可以访问那些资源,而 Cross-Origin Resource Sharing (CORS) 可以从资源服务端限制那些调用方可以访问资源。假设在前端的代码运行在 https://domain-a.com 的服务上,通过 XMLHttpRequest 来访问 https://domain-b.com/data.json 这个资源。一般来讲浏览器会阻止这次请求的结果,因为从安全的角度来看,这是属于 Cross-Domain。

如何避免这个问题呢?需要在资源服务端在返回结果的时候,Header 需要添加 Access-Control-Allow-Origin 这个字段,它表明这个资源可以被哪些 origin 访问。

一个简单的请求是这样的:

在这里 * 表示该资源可以被任何 cross-origin 的请求访问。

通常浏览器会发出一个 Preflighted request,该请求会发出 OPTIONS 这个方法,一般服务端的相应会包含 Access-Control-Allow-OriginAccess-Control-Allow-Methods 两个 header 字段。如果满足要求,才会发送真正的请求。

References

  1. https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
  2. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

A software developer in Microsoft at Suzhou. Most articles spoken language is Chinese. I will try with English when I’m ready

A software developer in Microsoft at Suzhou. Most articles spoken language is Chinese. I will try with English when I’m ready