客户的一个老的 web 项目升级后,页面无法加载,F12发现所有资源的协议都变成了HTTPS,然而这个项目实际上使用的是HTTP协议,并没有使用HTTPS,经过检查发现是页面中 head 界面里的一段代码导致的:

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

这段代码会将HTTP协议自动转换为HTTPS协议。删掉后页面恢复正常。

Content-Security-Policy

Content-Security-PolicyCSP)允许站点管理者控制用户代理能够为指定的页面加载哪些资源。除了少数例外情况,设置的政策主要涉及指定服务器的源和脚本结束点。这将帮助防止跨站脚本攻击(Cross-Site Script)。

CSP 的实质就是白名单制度,大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机。

两种方法可以启用 CSP。一种是通过 HTTP 头信息的Content-Security-Policy的字段。

另一种是通过网页的<meta>标签。

  • 脚本:只信任当前域名
  • <object>标签:不信任任何URL,即不加载任何资源
  • 样式表:只信任cdn.example.orgthird-party.org
  • 框架(frame):必须使用HTTPS协议加载
  • 其他资源:没有限制

限制选项

资源加载限制

以下选项限制各类资源的加载。

  • script-src:外部脚本
  • style-src:样式表
  • img-src:图像
  • media-src:媒体文件(音频和视频)
  • font-src:字体文件
  • object-src:插件(比如 Flash
  • child-src:框架
  • frame-ancestors:嵌入的外部资源(比如<frame><iframe><embed><applet>
  • connect-srcHTTP 连接(通过 XHRWebSocketsEventSource等)
  • worker-srcworker脚本
  • manifest-src:manifest 文件

default-src

default-src用来设置上面各个选项的默认值。

Content-Security-Policy: default-src 'self

上面代码限制所有的外部资源,都只能从当前域名加载。

如果同时设置某个单项限制(比如font-src)和default-src,前者会覆盖后者,即字体文件会采用font-src的值,其他资源依然采用default-src的值。

URL 限制

有时,网页会跟其他 URL 发生联系,这时也可以加以限制。

  • frame-ancestors:限制嵌入框架的网页
  • base-uri:限制<base#href>
  • form-action:限制<form#action>

其他限制

其他一些安全相关的功能,也放在了 CSP 里面。

  • block-all-mixed-contentHTTPS 网页不得加载 HTTP 资源(浏览器已经默认开启)
  • upgrade-insecure-requests:自动将网页上所有加载外部资源的 HTTP 链接换成 HTTPS 协议
  • plugin-types:限制可以使用的插件格式
  • sandbox:浏览器行为的限制,比如不能有弹出窗口等。