最近,阅读了一些非常好的关于https的博文:
- 关于启用 HTTPS 的一些经验分享(一)
- 关于启用 HTTPS 的一些经验分享(二)
- 使用 Wireshark 调试 HTTP/2 流量
- Referrer Policy 介绍
- 大型网站的 HTTPS 实践(四)——协议层以外的实践
摘录了其中一些内容,供后面参考:
关于Mixed Content
现代浏览器都在(开始在)遵循W3C Mixed Content,将 Mixed Content 分为 Optionally-blockable 和 Blockable 两类:
Optionally-blockable 类 Mixed Content 包含那些危险较小,即使被中间人篡改也无大碍的资源。现代浏览器默认会加载这类资源,同时会在控制台打印警告信息。这类资源包括:
- 通过
<img>
标签加载的图片(包括 SVG 图片); - 通过
<video> / <audio>
和<source>
标签加载的视频或音频; - 预读的(Prefetched)资源;
除此之外所有的 Mixed Content 都是 Blockable,浏览器必须禁止加载这类资源。所以现代浏览器中,对于 HTTPS 页面中的 JavaScript、CSS 等 HTTP 资源,一律不加载,直接在控制台打印错误信息。
合理使用 CSP (Content Security Policy)
block-all-mixed-content
通过 CSP 的 block-all-mixed-content
指令,可以让页面进入对混合内容的严格检测(Strict Mixed Content Checking)模式。在这种模式下,所有非 HTTPS 资源都不允许加载。跟其它所有 CSP 规则一样,可以通过以下两种方式启用这个指令:
HTTP 响应头方式:Content-Security-Policy: block-all-mixed-content
<meta>
标签方式:<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
upgrade-insecure-requests
通过 upgrade-insecure-requests 这个 CSP 指令,可以让浏览器帮忙做这个转换。启用这个策略后,有两个变化:
- 页面所有 HTTP 资源,会被替换为 HTTPS 地址再发起请求;
- 页面所有站内链接,点击后会被替换为 HTTPS 地址再跳转;
跟其它所有 CSP 规则一样,这个指令也有两种方式来启用,具体格式请参考上一节。需要注意的是 upgrade-insecure-requests
只替换协议部分,所以只适用于 HTTP/HTTPS 域名和路径完全一致的场景。
合理使用 HSTS
HSTS 基本使用
这个问题可以通过 HSTS(HTTP Strict Transport Security,RFC6797)来解决。HSTS 是一个响应头,格式如下:Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]
- max-age,单位是秒,用来告诉浏览器在指定时间内,这个网站必须通过 HTTPS 协议来访问。也就是对于这个网站的 HTTP 地址,浏览器需要先在本地替换为 HTTPS 之后再发送请求。
- includeSubDomains,可选参数,如果指定这个参数,表明这个网站所有子域名也必须通过 HTTPS 协议来访问。
- preload,可选参数,后面再介绍它的作用。
HSTS 这个响应头只能用于 HTTPS 响应;网站必须使用默认的 443 端口;必须使用域名,不能是 IP。而且启用 HSTS 之后,一旦网站证书错误,用户无法选择忽略。
HSTS Preload List
HTTPS 迁移遇到的一些常见问题。
传递 Referrer
我们可以把自己的网站替换为 https,但是一般的站点都有外链,要让外链都 https 目前还不太现实。很多网站需要从 referrer 中判断流量来源,因此对于搜索引擎这样的网站来说,referer 的传递还是比较重要的。如果不做任何设置,你会发现在 https 站点中点击外链并没有将 referrer 带入到 http 请求的头部中(http://tools.ietf.org/html/rfc7231#section-5.5.2 )。现代的浏览器可以用 meta 标签来传递 refer。(http://w3c.github.io/webappsec/specs/referrer-policy )
<meta name="referrer" content="always">
传递完整的 url
<meta name="referrer" content="origin">
只传递站点,不包含路径和参数等。
对于不支持 meta 传递 referrer 的浏览器,例如 IE8, 我们怎么办呢?
可以采用再次跳转的方法,既然 HTTPS 下不能给 HTTP 传递 referer,我们可以先从 HTTPS 访问一个可控的 http 站点,把需要传递的内容放到这个 http 站点的 url 中,然后再跳转到目标地址。