你以为 HTTPS 就是"加个 S"?其实它背后是一整张安全大网。
2011年,荷兰一家叫 Diginotar 的 CA 公司被黑客入侵。
黑客给自己签发了一张 google.com 的"合法证书"。全球访问 Google 的用户被悄悄劫持了 6 周,直到事情败露。
这件事后来催生了一系列安全机制。如果你也在做网站,这套机制跟你有关。
原文地址
证书是个什么东西
你访问 https://bank.com,浏览器拿到一张证书。证书里写着"我是 bank.com",由某家 CA 签发。
但浏览器为什么会信这张证书?
因为你的电脑操作系统里早就装好了这 CA 的"根证书"------信任的起点。Apple 、Microsoft 、Google 这些厂商在操作系统里预装了一批根证书,替我们做了第一步信任决策。
证书链长这样:
arduino
根证书(操作系统内置)
↓ 签发
中间证书(CA 的"分公司")
↓ 签发
网站证书(网站用的)
根证书是"超级 VIP",一旦泄露全世界都受影响。中间证书是"挡箭牌",出了问题可以单独吊销,不影响根证书。
签发证书就像办身份证:你准备好个人信息,去 CA 申请,CA 核实你是你,给你盖章发证。CSR (Certificate Signing Request ,证书签名请求)是办证时填的那张表。
自签名证书 就是自己给自己办的"假身份证"。内网测试、IoT 设备、VPN 可以用,浏览器不认,会弹警告。
CT Logs:给证书办"公示"
前面 Diginotar 那事儿证明:CA 也可能被入侵,也可能被贿赂,也可能出错。
如果一家 CA 偷偷给 google.com 签了证书,谁能发现?
2013年 Google 主导推出 CT Logs(Certificate Transparency)。所有公开证书必须提交到公开日志,任何人能查。
像不像给证书办"公示"?如果 google.com 突然多了一张奇怪的证书,Google 自己就能查到并申请吊销。
Chrome 从 2018 年起强制要求公开证书必须带 CT Logs 证据,否则直接拒绝。
OCSP Stapling:让服务器替浏览器跑腿
证书可能会"过期作废"------公司倒闭了,或者私钥泄露了。浏览器怎么知道手上的证书还活着?
传统做法是浏览器去问 CA 。听起来简单,但有两个坑:一是慢,每次访问都要多问一次;二是 CA 知道你访问了哪些网站,隐私全暴露。
服务器能不能替浏览器问一次呢?能。
服务器每隔几小时问一次 CA ,拿到 OCSP (Online Certificate Status Protocol ,在线证书状态协议 )响应,钉在证书里 一起发给浏览器。这就是 Stapling(钉子)的名字由来。
swift
没 Stapling:
浏览器 ──问 CA──> CA
浏览器 ──问服务器──> 服务器
有 Stapling:
服务器 ──问 CA──> CA(提前问好缓存着)
浏览器 ──问服务器──> 服务器(证书 + OCSP 响应一并发过来)
就像咖啡店每天早上提前问供应商"今天牛奶到不到货",顾客点单时直接知道结果。
HSTS:第一次访问的"信任名单"
你输入 bank.com(不带 https)。浏览器默认用 HTTP 访问,请求被劫持到假的银行网站。
即使服务器支持 HTTPS ,第一次访问还是裸奔的------因为浏览器还不知道这个网站要走 HTTPS。
服务器怎么告诉浏览器"我以后都用 HTTPS "?返回一个小票(HTTP 响应头):
ini
Strict-Transport-Security: max-age=31536000; includeSubDomains
意思是未来一年内,访问 bank.com 和所有子域名必须用 HTTPS ,哪怕你输入的是 HTTP。第一次访问可能被劫持,第二次开始就安全了。
但第一次还是裸奔怎么办?
Chrome 维护了一份 HSTS 预加载列表 ,写进 Chrome 源码里。网站申请加入、Chrome 审核通过后,第一次访问就强制 HTTPS。
打开 hstspreload.org 看看你的网站加没加入这个"VIP 名单"。
CSP:给资源加载装"门禁"
HTTPS 防的是"传输层"------数据从 A 到 B 中间不被偷看。
但如果你的网站被注入了 XSS (Cross-Site Scripting ,跨站脚本攻击 )脚本,HTTPS 也没用。脚本是在你自己的网站里运行的,等于"内鬼"。
CSP (Content Security Policy ,内容安全策略)是给资源加载装门禁:服务器通过响应头告诉浏览器"我这个页面只允许加载这些资源"。
yaml
Content-Security-Security:
default-src 'self';
script-src 'self' cdn.com;
img-src *;
style-src 'self' 'unsafe-inline';
像不像小区门禁?默认只让本小区的人进('self'),特殊人员(cdn.com)登记后可进。
html
<script src="evil.com/x.js"></script> ← 直接被拦截
<img src="anywhere.com/y.jpg"> ← 允许(图片不限)
即使黑客注入了 <script>,引用的 JS 不在白名单里,根本加载不了。
那个 nonce 是临时暗号:每个 <script> 标签带一个随机值,服务器下发的 CSP 里也包含这个值。黑客不知道暗号,就注入不了脚本。
xml
CSP 门禁系统:
黑客想注入 <script src="evil.com/x.js">
│
▼
┌─────────────────────────────────┐
│ CSP 门禁(小区保安) │
│ │
│ default-src 'self' │
│ script-src 'self' cdn.com │
│ │
│ evil.com 在不在白名单? │
│ │ │
│ ▼ │
│ 不在 → 拦截! │
└─────────────────────────────────┘
│
▼
恶意脚本加载失败,页面安全
那个 nonce 是临时暗号:每个 <script> 标签带一个随机值,服务器下发的 CSP 里也包含这个值。黑客不知道暗号,就注入不了脚本。
mTLS:双方都得证明"我是我"
普通 HTTPS 是单向认证:服务器证明自己是真的,客户端不用证明。
客户端:我是浏览器
服务器:我是 bank.com(这是我的身份证)
像不像你去咖啡店买咖啡,店员向你出示"我是这家店员"的工作证明,你不用出示身份证?
mTLS(mutual TLS)是双方都认证:
客户端:我是 app-x(这是我的身份证)
服务器:我是 bank.com(这是我的身份证)
服务器也要验证客户端的身份证。
用在银行后台系统、IoT 设备、企业内部 API。普通网站不用,太麻烦了。
混合内容:HTTPS 页面里的"老鼠屎"
HTTPS 页面里如果加载了 HTTP 资源(图片、JS 、CSS ),就叫混合内容。
html
<script src="http://example.com/x.js"></script> ← 主动混合内容
<img src="http://example.com/y.jpg"> ← 被动混合内容
就像你穿了一身铠甲,但腰上挂了个塑料袋。
浏览器策略:主动混合内容(JS 、iframe)直接拦截,页面可能坏掉;被动混合内容(图片、视频)警告但允许。
Chrome DevTools 的 Console 会看到黄色警告。或者用 Why No Padlock 这种工具查。
常见配置错误
证书过期 :Let's Encrypt 证书只有 90 天,自动化续签没做好就过期了。
证书不匹配域名 :证书是 www.example.com 的,但你访问的是 api.example.com。
不完整的证书链:服务器只发了网站证书,没发中间证书。正确做法是把整条链都发出去。
弱加密算法 :MD5、SHA1 这些老算法已经能被破解了。推荐 AES-128-GCM、ChaCha20、SHA-256。
TLS 版本太低 :TLS 1.0 、TLS 1.1 早就不安全了,至少 TLS 1.2 ,推荐 TLS 1.3 。TLS 是 HTTPS 背后的加密协议,1.3 是最新版本,握手更快更安全。
怎么检查你的 HTTPS 配置
SSL Labs 是最权威的:访问 www.ssllabs.com/ssltest/,输入域名,几分钟后给一份详细报告(A+、A、B、C...)。
testssl.sh 是命令行工具:
bash
brew install testssl
testssl example.com
Chrome DevTools 的 Security 面板能看证书、协议版本、加密套件、混合内容。
性能优化
加密会影响性能,但有几个方法可以优化:
TLS 1.3 把握手从 2 次往返变成 1 次往返,快一倍。建立 HTTPS 连接需要"打几个招呼"才能开始传数据,TLS 1.3 少打一个。
会话恢复让第二次访问不用重新握手。像不像你办了健身卡,下次去直接刷卡,不用每次都填表。
OCSP Stapling 前面讲了,少一次网络请求。
硬件加速让 CPU 直接硬件加速加密,几乎不影响性能。现代 CPU 都支持。
HTTPS 不是"加个 S"那么简单。它背后是一张安全大网:证书链解决"信谁"、CT Logs 防止 CA 乱来、OCSP Stapling 解决"慢"和"隐私"、HSTS 防止"第一次裸奔"、CSP 防 XSS 、mTLS 用于双向认证。
配置完了别忘了用 SSL Labs 跑一次,看看你的网站能拿几分。