前言
你有没有注意过,浏览器地址栏有时候会显示一个小锁头图标 🔒?这就是 HTTPS 在保护你。
当你在淘宝买东西、在网银转账、在微信网页版聊天时,HTTPS 就像一个隐形的保镖,默默保护着你的信息安全。
今天,我用最简单的方式,带你理解 HTTPS 是如何工作的。
一、HTTP 和 HTTPS 的区别
想象你在寄信:
-
HTTP = 明信片 📮
- 内容写在明信片上,邮递员、分拣员、任何经手的人都能看到你写了什么
- 如果你在明信片上写"我的银行卡密码是123456",所有人都能看到
-
HTTPS = 带锁的信封 🔐
- 内容被锁在信封里,只有收件人有钥匙打开
- 即使有人偷走了信封,也看不到里面的内容
简单说:HTTP 是裸奔,HTTPS 是穿盔甲。
二、HTTPS 的三个核心问题
HTTPS 要解决三个问题:
- 加密:内容只有发送方和接收方能看懂
- 身份验证:你访问的网站是真的,不是假冒的
- 完整性:内容在传输过程中没有被篡改
我们一个一个来说。
三、加密:把信息变成"天书"
3.1 对称加密(用同一把钥匙)
想象你和朋友各有一把一模一样的钥匙 🔑,你们约定好:
- 你用这把钥匙把信锁进盒子里
- 朋友用同一把钥匙打开盒子
这就是对称加密:加密和解密用同一把钥匙。
问题:怎么把钥匙安全地给朋友呢?如果寄钥匙的时候被人截获了,别人也能打开你的盒子。
3.2 非对称加密(两把不同的钥匙)
这个方法更聪明,每个人有两把钥匙:
- 公钥 🔓:可以公开给所有人,用来加密
- 私钥 🔐:只有自己知道,用来解密
就像一个特殊的信箱:
- 任何人都可以从缝隙把信投进去(用公钥加密)
- 但只有有信箱钥匙的人才能打开取信(用私钥解密)
好处:公钥可以随便发,不用担心被截获,因为没有私钥就解不开。
3.3 HTTPS 的加密方案
HTTPS 聪明地结合了两种加密方式:
- 先用非对称加密安全地交换一把对称密钥
- 之后的通信都用这把对称密钥(因为对称加密更快)
就像:
- 我先用你的公钥把一把新钥匙寄给你(安全)
- 以后我们用这把新钥匙通信(快速)
四、数字证书:网站的身份证明
这是 HTTPS 最重要也最有趣的部分。
4.1 为什么需要证书?
假设你要登录银行网站:
你:我要登录我的银行账户
假网站:好的,我是银行,把密码给我吧
你:这是我的密码... 💰
假网站:谢谢,钱我拿走了 😈
这就是中间人攻击:有人假冒银行网站骗你的密码。
证书就是用来证明"我是真的银行,不是骗子"。
4.2 证书长什么样?
数字证书就像一张电子身份证,包含:
- 网站的域名(如 www.icbc.com.cn)
- 网站公司的名称
- 证书的有效期
- 网站的公钥
- 签发机构(CA)的签名
4.3 谁来发证书?CA(证书颁发机构)
CA 就像是互联网的"公安局户籍科",负责核实网站身份并颁发证书。
知名的 CA 有:
- DigiCert
- Let’s Encrypt(免费)
- GlobalSign
- Symantec
4.4 证书的信任链
你可能会问:我怎么知道 CA 是真的?
答案是:你的电脑/手机出厂时,已经预装了根证书,里面包含了所有受信任的 CA 的公钥。
信任链是这样的:
graph TD
A[根CA<br/>你电脑信任的] -->|签发| B[中间CA]
B -->|签发| C[网站证书]
style A fill:#e1f5ff
style B fill:#fff4e1
style C fill:#e8f5e9
就像:
- 国家信任省政府
- 省政府信任市公安局
- 市公安局给你发身份证
所以,当你看到一个网站的证书是由某个 CA 签发的,而你的电脑信任这个 CA,你就信任这个网站。
4.5 CA 如何验证网站身份?
当你申请证书时,CA 会核实:
-
域名验证(DV):证明你拥有这个域名
- 最简单,发邮件到域名邮箱确认
- 几分钟就能拿到
-
组织验证(OV):验证公司/组织真实性
- 检查公司注册信息
- 电话验证
- 需要几天
-
扩展验证(EV):最严格的验证
- 深度调查公司背景
- 法律文件审核
- 需要几周
- 浏览器会显示公司名称(绿色地址栏)
4.6 证书签名:防伪技术
CA 给网站发证书时,会做一个数字签名。
签名过程:
- CA 把证书内容计算出一个"指纹"(哈希值)
- CA 用自己的私钥加密这个指纹
- 加密后的指纹就是"签名"
验证过程:
- 浏览器用 CA 的公钥解密签名,得到指纹
- 浏览器自己计算证书内容的指纹
- 如果两个指纹一样,说明证书是真的
为什么不能伪造?
- 没有 CA 的私钥,就无法生成有效签名
- 修改证书任何内容,指纹就会变化,验证失败
4.7 证书验证:浏览器如何确认证书有效?
当你访问一个 HTTPS 网站时,浏览器会自动进行一系列检查,确保证书是真实有效的。这个过程就像安检员检查身份证一样严格。
第一步:检查证书链(信任链验证)
浏览器会验证证书的"家谱":
graph TD
A[网站证书] -->|由谁签发| B[中间CA证书]
B -->|由谁签发| C[根CA证书]
C -->|是否在信任列表| D{浏览器信任库}
D -->|是| E[✅ 信任链有效]
D -->|否| F[❌ 不受信任]
style E fill:#d4edda
style F fill:#f8d7da
检查过程:
- 浏览器拿到网站证书,看到是"中间CA A"签发的
- 浏览器拿到"中间CA A"的证书,看到是"根CA B"签发的
- 浏览器检查"根CA B"是否在自己预装的信任列表中
- 如果在,信任链验证通过 ✅
为什么不能伪造?
- 攻击者可以伪造网站证书,但无法伪造CA的签名
- 没有CA的私钥,就无法生成有效的签名
- 浏览器只会信任预装的根CA
第二步:检查有效期
每个证书都有"保质期":
证书有效期:
开始时间:2025-01-01 00:00:00
结束时间:2026-12-31 23:59:59
浏览器会对比当前时间:
- 未生效:当前时间 < 开始时间 → ❌ 拒绝
- 已过期:当前时间 > 结束时间 → ❌ 拒绝
- 有效期内 → ✅ 通过
为什么需要有效期?
- 限制证书被盗用的风险窗口
- 定期更新加密算法和密钥强度
- CA定期重新验证网站身份
第三步:检查域名匹配
证书是绑定特定域名的,就像身份证绑定特定的人:
证书中的域名:www.example.com
你访问的地址:www.example.com ✅ 匹配
证书中的域名:www.example.com
你访问的地址:mail.example.com ❌ 不匹配
浏览器会检查:
- 证书中的"主题名称"(CN)是否与你访问的域名匹配
- 证书中的"主题备用名称"(SAN)列表是否包含你的域名
注意:
example.com和www.example.com是不同的域名- 通配符证书
*.example.com可以匹配所有子域名 - IP地址也可以在证书中,但很少见
第四步:检查证书吊销状态
有时候,证书还在有效期内,但已经被"注销"了:
什么情况下证书会被吊销?
- 网站私钥泄露
- 发现证书被滥用
- 网站身份信息变更
- CA违规操作
如何检查吊销状态?
浏览器有两种方式:
方式1:CRL(证书吊销列表)
就像"黑名单":
1. CA维护一个列表,包含所有被吊销的证书编号
2. 浏览器下载这个列表
3. 检查当前证书是否在黑名单中
缺点:
- 列表会越来越大
- 更新不及时(可能几天才更新一次)
方式2:OCSP(在线证书状态协议)
sequenceDiagram
participant 浏览器
participant OCSP服务器
浏览器->>OCSP服务器: 这个证书还有效吗?
OCSP服务器->>浏览器: 有效/已吊销/未知
优点:
- 实时查询
- 响应快
缺点:
- 暴露用户访问了哪些网站(隐私问题)
- 如果OCSP服务器挂了,怎么办?
方式3:OCSP Stapling(OCSP装订)
改进方案:让网站服务器预先获取OCSP响应,随证书一起发给浏览器:
sequenceDiagram
participant 服务器
participant OCSP服务器
participant 浏览器
服务器->>OCSP服务器: 预先查询我的证书状态
OCSP服务器->>服务器: 返回签名证明(有效期1-2天)
服务器->>浏览器: 证书 + OCSP证明
浏览器->>浏览器: 验证OCSP证明签名
优点:
- 保护用户隐私
- 减少浏览器请求
- 即使OCSP服务器宕机也能工作
第五步:验证数字签名
最后,浏览器会验证证书的"防伪标签":
验证过程:
-
计算指纹:浏览器用同样的哈希算法计算证书内容的指纹
证书内容 → SHA-256哈希 → 指纹A -
解密签名:用CA的公钥解密证书上的签名
签名 → 用CA公钥解密 → 指纹B -
对比指纹:
指纹A == 指纹B ? 相等 → ✅ 签名有效,证书未被篡改 不相等 → ❌ 签名无效,证书被篡改或伪造
为什么不能伪造?
- 没有CA的私钥,就无法生成能被CA公钥解密的签名
- 修改证书任何内容,指纹都会变化,导致验证失败
验证流程总结
flowchart TD
A[收到网站证书] --> B{信任链验证}
B -->|失败| Z[❌ 连接失败]
B -->|通过| C{有效期验证}
C -->|未生效/已过期| Z
C -->|有效| D{域名匹配验证}
D -->|不匹配| Z
D -->|匹配| E{吊销状态验证}
E -->|已吊销| Z
E -->|未吊销| F{签名验证}
F -->|无效| Z
F -->|有效| G[✅ 证书有效,建立连接]
style G fill:#d4edda
style Z fill:#f8d7da
只有所有检查都通过,浏览器才会建立安全连接。任何一项失败,都会显示警告页面。
浏览器警告解读
当验证失败时,浏览器会显示不同的错误信息:
| 错误类型 | 含义 | 可能原因 |
|---|---|---|
| NET::ERR_CERT_AUTHORITY_INVALID | 证书不是受信任的CA签发 | 自签名证书、CA不受信任 |
| NET::ERR_CERT_DATE_INVALID | 证书已过期或未生效 | 证书过期、系统时间错误 |
| NET::ERR_CERT_COMMON_NAME_INVALID | 域名不匹配 | 访问的域名与证书域名不符 |
| NET::ERR_CERT_REVOKED | 证书已被吊销 | 私钥泄露、CA主动吊销 |
| NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM | 签名算法太弱 | 使用过时的SHA-1等算法 |
| NET::ERR_SSL_PINNED | 证书固定失败 | 证书被更换(可能是攻击) |
看到警告怎么办?
- 如果是正规网站(银行、电商等):不要继续访问,可能是钓鱼网站
- 如果是内部测试环境:可能是配置问题,需要手动信任证书
- 检查系统时间是否正确(时间错误会导致证书验证失败)
五、HTTPS 完整工作流程
现在我们把所有内容串起来,看看 HTTPS 是如何工作的:
5.1 握手阶段(建立安全连接)
sequenceDiagram
participant 浏览器
participant 服务器
浏览器->>服务器: 1. 你好,我想建立HTTPS连接
服务器->>浏览器: 2. 好的,这是我的证书(包含公钥)
浏览器->>浏览器: 3. 验证证书是否有效
浏览器->>服务器: 4. 生成对称密钥,用公钥加密后发送
服务器->>服务器: 5. 用私钥解密,得到对称密钥
Note over 浏览器,服务器: 6. 握手完成,开始用对称密钥加密通信
这个过程叫 TLS 握手,通常只需要几百毫秒。
5.2 数据传输阶段
握手完成后,双方用协商好的对称密钥加密所有数据:
你:[加密] "我的密码是 xxx"
网站:[解密] 收到密码,验证中...
网站:[加密] "登录成功!"
你:[解密] 太好了!
六、HTTPS 如何保证安全性
6.1 防止窃听(加密)
即使黑客截获了你的数据包,看到的也是乱码:
原始数据:{"password": "123456"}
加密后:U2FsdGVkX1+8Y7Z3hN4pQw==
没有密钥,黑客无法解密。
6.2 防止假冒(证书)
当你访问银行网站时:
- 浏览器收到证书
- 检查证书是不是受信任的 CA 签发的
- 检查证书的域名是否匹配
- 检查证书是否过期
- 检查证书是否被吊销
任何一项失败,浏览器就会警告你:
⚠️ 您的连接不是私密连接
攻击者可能试图从 xxx 窃取您的信息
6.3 防止篡改(消息认证码)
HTTPS 会给每个数据包加一个"封条"(MAC):
- 发送方计算数据的校验码
- 接收方收到后重新计算
- 如果校验码不匹配,说明数据被改过
七、开发中的 HTTPS 抓包
在开发和测试过程中,我们经常需要查看 HTTPS 请求的详细内容(比如接口参数、响应数据)。但 HTTPS 是加密的,如何才能看到明文内容呢?
7.1 为什么需要抓包?
常见场景:
- 调试 API 接口,查看请求参数和响应内容
- 分析第三方 App 的网络请求
- 排查网络问题
- 安全测试
问题:HTTPS 数据是加密的,直接抓包只能看到乱码。
7.2 抓包的原理:中间人(MITM)
还记得我们前面说的"中间人攻击"吗?抓包工具其实就是"合法的中间人"。
正常 HTTPS 通信:
sequenceDiagram
participant App as 手机App
participant Server as 服务器
App->>Server: 建立HTTPS连接
Server->>App: 返回证书
App->>App: 验证证书✅
App->>Server: 加密通信 🔐
使用抓包工具时:
sequenceDiagram
participant App as 手机App
participant Proxy as 抓包工具<br/>(中间人)
participant Server as 服务器
Note over App,Proxy: 连接1: App ↔ 抓包工具
App->>Proxy: 建立HTTPS连接
Proxy->>App: 返回抓包工具的证书
App->>App: 验证证书✅(需手动信任)
App->>Proxy: 加密通信 🔐
Note over Proxy,Server: 连接2: 抓包工具 ↔ 服务器
Proxy->>Server: 建立HTTPS连接
Server->>Proxy: 返回服务器证书
Proxy->>Proxy: 验证证书✅
Proxy->>Server: 加密通信 🔐
Note over App,Server: 抓包工具解密 → 查看 → 重新加密
关键点:
- 抓包工具与 App 建立一个 HTTPS 连接(用抓包工具的证书)
- 抓包工具与服务器建立另一个 HTTPS 连接(用服务器的证书)
- 抓包工具在中间解密 → 查看/修改 → 重新加密
- 前提:App 必须信任抓包工具的证书
7.3 如何实现抓包?
步骤1:安装抓包工具
常用的抓包工具有:
| 工具 | 平台 | 特点 |
|---|---|---|
| Charles | macOS/Windows/Linux | 图形界面,易用,收费 |
| Fiddler | Windows | 免费,功能强大 |
| mitmproxy | 跨平台 | 命令行,可编程,免费 |
| Proxyman | macOS | 界面美观,免费版够用 |
步骤2:配置抓包工具的代理
让手机的网络请求通过电脑上的抓包工具:
手机 → WiFi设置 → 代理 → 手动
代理主机:电脑的IP地址(如 192.168.1.100)
代理端口:8888(Charles默认)
步骤3:安装并信任抓包工具的证书
这是最关键的一步!
为什么需要安装证书?
- 抓包工具要充当"中间人"
- 它需要生成伪造的证书给 App
- App 默认不信任这个证书
- 你需要手动安装并信任
在手机上安装证书(以 Charles 为例):
-
下载证书
Charles → Help → SSL Proxying → Install Charles Root Certificate on a Mobile Device会显示一个网址,手机浏览器打开下载
-
安装证书(iOS)
设置 → 已下载描述文件 → 点击安装 输入密码确认 -
信任证书(iOS 重要!)
设置 → 通用 → 关于本机 → 证书信任设置 找到 Charles 证书,打开开关 ✅注意:只安装还不够,必须在这里开启信任!
-
安装证书(Android)
设置 → 安全 → 加密与凭据 → 安装证书 → CA 证书 选择下载的证书文件
步骤4:启用 SSL 代理
在抓包工具中配置要抓取的域名:
Charles:
Proxy → SSL Proxying Settings
勾选 Enable SSL Proxying
Add → Host: * (或指定域名), Port: 443
mitmproxy:
# 默认会拦截所有HTTPS流量
mitmproxy -p 8888
步骤5:开始抓包
现在打开手机上的 App,抓包工具就能看到解密后的 HTTPS 请求了:
GET https://api.example.com/user/profile
Headers:
Authorization: Bearer xxxxxx
Content-Type: application/json
Response:
{
"id": 12345,
"name": "张三",
"email": "zhangsan@example.com"
}
7.4 常见问题
Q1:为什么有些 App 抓不到包?
原因1:证书固定(SSL Pinning)
有些 App 会"记住"服务器的证书,只接受特定证书:
flowchart TD
A[App发起请求] --> B{检查证书}
B -->|是服务器证书| C[✅ 正常连接]
B -->|是抓包工具证书| D[❌ 拒绝连接]
style C fill:#d4edda
style D fill:#f8d7da
解决方案:
- 使用 Frida、Xposed 等工具绕过 SSL Pinning
- 反编译 App,移除证书固定代码
- 使用 App 的测试版本(通常没有 Pinning)
原因2:双向认证(Mutual TLS)
有些高安全性 App(如银行)要求客户端也提供证书:
sequenceDiagram
participant App
participant Server
App->>Server: 这是我的客户端证书
Server->>Server: 验证客户端证书✅
Server->>App: 这是我的服务器证书
App->>App: 验证服务器证书✅
Note over App,Server: 双向验证通过,开始通信
这种情况下,抓包工具没有客户端证书,无法建立连接。
Q2:抓包安全吗?
在开发环境:✅ 安全
- 只抓取你自己的设备流量
- 证书只在你设备上信任
在公共 WiFi:❌ 危险!
- 不要在公共 WiFi 上进行敏感操作
- 攻击者可能用同样的方法窃取你的数据
- 这就是为什么 HTTPS 如此重要!
Q3:如何防止被别人抓包?
如果你是 App 开发者,可以:
-
启用 SSL Pinning
只信任特定证书,拒绝抓包工具的证书 -
使用双向认证
客户端和服务器互相验证证书 -
数据加密
即使被抓包,数据也是二次加密的 -
检测代理
App 检测是否设置了代理,拒绝在代理环境下运行
7.5 抓包工具对比
| 功能 | Charles | Fiddler | mitmproxy | Proxyman |
|---|---|---|---|---|
| 图形界面 | ✅ | ✅ | ❌ | ✅ |
| 免费 | ❌ | ✅ | ✅ | 部分 |
| 脚本功能 | ❌ | ✅ | ✅ | ✅ |
| 重放请求 | ✅ | ✅ | ✅ | ✅ |
| 修改请求 | ✅ | ✅ | ✅ | ✅ |
| 移动端支持 | ✅ | ✅ | ✅ | ✅ |
| macOS | ✅ | ❌ | ✅ | ✅ |
| Windows | ✅ | ✅ | ✅ | ❌ |
| Linux | ✅ | ❌ | ✅ | ❌ |
推荐:
- macOS 用户:Proxyman(免费版)或 Charles(付费)
- Windows 用户:Fiddler(免费)
- 开发者/自动化:mitmproxy(可编程)
7.6 实战技巧
技巧1:过滤请求
只看关心的请求,避免被大量请求淹没:
Charles 过滤器:
Include: api.example.com/*
Exclude: *.jpg, *.png, *.css, *.js
技巧2:断点调试
在请求发出前或响应返回前暂停,修改数据:
sequenceDiagram
participant App
participant Proxy as 抓包工具
participant Server
App->>Proxy: 准备发送请求
Note over Proxy: ⏸️ 断点暂停
Note over Proxy: 修改参数: price=99 → price=9
Proxy->>Server: 发送修改后的请求
Server->>Proxy: 返回响应
Note over Proxy: ⏸️ 断点暂停
Note over Proxy: 修改响应: balance=1000 → balance=9999
Proxy->>App: 返回修改后的响应
用途:
- 测试边界条件(负数、超大值等)
- 模拟服务器错误
- 绕过前端验证
技巧3:保存和重放
保存请求,随时重放:
1. 右键请求 → Export
2. 保存为 .chlsj 文件(Charles)或 .saz 文件(Fiddler)
3. 随时导入并重放
用途:
- 复现 Bug
- 自动化测试
- 分享给同事
七、常见问题
Q1:HTTPS 完全安全吗?
不是 100% 安全,但比 HTTP 安全得多。
可能的攻击方式:
- 钓鱼网站:用户访问了假网站(但假网站没有真证书)
- 根证书被攻破:极其罕见,但理论上可能
- 用户自己点击"继续访问不安全网站":人为因素
Q2:为什么有些网站还是 HTTP?
原因:
- 以前证书要花钱(现在 Let’s Encrypt 免费)
- 需要技术配置
- 部分老网站还没升级
- 某些内网系统不需要
现在主流浏览器对 HTTP 网站会显示"不安全"警告,推动网站升级。
Q3:我自己能看证书吗?
可以!操作方法:
Chrome 浏览器:
- 点击地址栏的 🔒 图标
- 点击"连接是安全的"
- 点击"证书有效"
- 就能看到证书的详细信息
Q4:免费证书和付费证书有什么区别?
| 项目 | Let’s Encrypt(免费) | 付费证书 |
|---|---|---|
| 安全性 | 一样 | 一样 |
| 有效期 | 90天 | 1-2年 |
| 验证级别 | 域名验证 | 可选 OV/EV |
| 技术支持 | 社区 | 客服 |
| 适合 | 个人博客、小网站 | 企业网站 |
八、总结
用一句话总结 HTTPS:
HTTPS = HTTP + TLS/SSL 加密协议 + 数字证书
它通过三个机制保护你:
- 加密:用数学方法把信息变成乱码,只有对方能解开
- 证书:像身份证一样证明网站是真的,不是假冒的
- 完整性:确保数据在传输过程中没有被篡改
下次看到浏览器地址栏的小锁头 🔒,你就知道它在默默保护你了。
扩展阅读
作者注:本文故意简化了一些技术细节(如 RSA、ECC、TLS 1.3 等),以便让非技术读者也能理解。如果你想深入了解,可以查阅相关技术文档。