关于启用 HTTPS 的一些经验分享

发布时间:2025-04-21 点击:3
随着国内网络环境的持续恶化,各种篡改和劫持层出不穷,越来越多的网站选择了全站 https。https 通过 tls 层和证书机制提供了内容加密、身份认证和数据完整性三大功能,可以有效防止数据被查看或篡改,以及防止中间人冒充。本文分享一些启用 https 过程中的经验,重点是如何与一些新出的安全规范配合使用。至于 https 的部署及优化,之前写过很多,本文不重复了。
理解 mixed content
https 网页中加载的 http 资源被称之为 mixed content(混合内容),不同浏览器对 mixed content 有不一样的处理规则。
早期的 ie
早期的 ie 在发现 mixed content 请求时,会弹出「是否只查看安全传送的网页内容?」这样一个模态对话框,一旦用户选择「是」,所有 mixed content 资源都不会加载;选择「否」,所有资源都加载。
比较新的 ie
比较新的 ie 将模态对话框改为页面底部的提示条,没有之前那么干扰用户。而且默认会加载图片类 mixed content,其它如 javascript、css 等资源还是会根据用户选择来决定是否加载。
现代浏览器
现代浏览器(chrome、firefox、safari、microsoft edge),基本上都遵守了 w3c 的 mixed content 规范,将 mixed content 分为optionally-blockable 和 blockable 两类:
optionally-blockable 类 mixed content 包含那些危险较小,即使被中间人篡改也无大碍的资源。现代浏览器默认会加载这类资源,同时会在控制台打印警告信息。这类资源包括:
通过 标签加载的图片(包括 svg 图片);
通过 <img> 标签加载的图片(包括 svg 图片);
通过 <video> / <audio> 和 <source> 标签加载的视频或音频;
预读的(prefetched)资源;
预读的(prefetched)资源;
除此之外所有的 mixed content 都是 blockable,浏览器必须禁止加载这类资源。所以现代浏览器中,对于 https 页面中的 javascript、css 等 http 资源,一律不加载,直接在控制台打印错误信息。
移动浏览器
前面所说都是桌面浏览器的行为,移动端情况比较复杂,当前大部分移动浏览器默认都允许加载 mixed content。也就是说,对于移动浏览器来说,https 中的 http 资源,无论是图片还是 javascript、css,默认都会加载。
一般选择了全站 https,就要避免出现 mixed content,页面所有资源请求都走 https 协议才能保证所有平台所有浏览器下都没有问题。
合理使用 csp
csp,全称是 content security policy,它有非常多的指令,用来实现各种各样与页面内容安全相关的功能。
block-all-mixed-content
前面说过,对于 https 中的图片等 optionally-blockable 类 http 资源,现代浏览器默认会加载。图片类资源被劫持,通常不会有太大的问题,但也有一些风险,例如很多网页按钮是用图片实现的,中间人把这些图片改掉,也会干扰用户使用。
通过 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
历史悠久的大站在往 https 迁移的过程中,工作量往往非常巨大,尤其是将所有资源都替换为 https 这一步,很容易产生疏漏。即使所有代码都确认没有问题,很可能某些从数据库读取的字段中还存在 http 链接。
而通过 upgrade-insecure-requests 这个 csp 指令,可以让浏览器帮忙做这个转换。启用这个策略后,有两个变化:
页面所有 http 资源,会被替换为 https 地址再发起请求;
页面所有站内链接,点击后会被替换为 https 地址再跳转;
跟其它所有 csp 规则一样,这个指令也有两种方式来启用,具体格式请参考上一节。需要注意的是 upgrade-insecure-requests 只替换协议部分,所以只适用于 http/https 域名和路径完全一致的场景。
合理使用 hsts
在网站全站 https 后,如果用户手动敲入网站的 http 地址,或者从其它地方点击了网站的 http 链接,依赖于服务端 301/302 跳转才能使用 https 服务。而第一次的 http 请求就有可能被劫持,导致请求无法到达服务器,从而构成 https 降级劫持。
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
可以看到 hsts 可以很好的解决 https 降级攻击,但是对于 hsts 生效前的首次 http 请求,依然无法避免被劫持。浏览器厂商们为了解决这个问题,提出了 hsts preload list 方案:内置一份列表,对于列表中的域名,即使用户之前没有访问过,也会使用 https 协议;列表可以定期更新。
目前这个 preload list 由 google chrome 维护,chrome、firefox、safari、ie 11 和 microsoft edge 都在使用。如果要想把自己的域名加进这个列表,首先需要满足以下条件:
拥有合法的证书(如果使用 sha-1 证书,过期时间必须早于 2016 年);
将所有 http 流量重定向到 https;
确保所有子域名都启用了 https;
输出 hsts 响应头:
max-age 不能低于 18 周(10886400 秒);
必须指定 includesubdomains 参数;
必须指定 preload 参数;
即便满足了上述所有条件,也不一定能进入 hsts preload lis。通过 chrome 的 chrome://net-internals/#hsts 工具,可以查询某个网站是否在 preload list 之中,还可以手动把某个域名加到本机 preload list。
对于 hsts 以及 hsts preload list,我的建议是只要你不能确保永远提供 https 服务,就不要启用。因为一旦 hsts 生效,你再想把网站重定向为 http,之前的老用户会被无限重定向,唯一的办法是换新域名。
cdn 安全
对于大站来说,全站迁移到 https 后还是得用 cdn,只是必须选择支持 https 的 cdn 了。如果使用第三方 cdn,安全方面有一些需要考虑的地方。
合理使用 sri
https 可以防止数据在传输中被篡改,合法的证书也可以起到验证服务器身份的作用,但是如果 cdn 服务器被入侵,导致静态文件在服务器上被篡改,https 也无能为力。
w3c 的 sri(subresource integrity)规范可以用来解决这个问题。sri 通过在页面引用资源时指定资源的摘要签名,来实现让浏览器验证资源是否被篡改的目的。只要页面不被篡改,sri 策略就是可靠的。


阿里云服务器配置要多久
小鸟云服务器配置推荐
企业建网站之后还要做哪些
阿里云服务器怎么找到实例
史上最贵二数字?币圈终端超4000万拿下60.com
换阿里云服务器重新备案
之前也访问不了说是实名未通过
状态正在连接状态连接建立