HTTPS:让数据传输更安全|浏览器篇
# HTTPS:让数据传输更安全
30 秒速记
HTTP明文传输不提供通信内容的保密性和完整性,沿途节点可以看到或修改数据。- 请求从用户电脑经 WiFi 路由器、运营商到目标服务器,链路中的任一环节都可能成为攻击位置。
- 中间人不仅能窃取内容,还能伪造响应或篡改请求,因此风险不止是隐私泄露。
- 终端恶意软件和钓鱼 WiFi 都属于可感知的攻击入口:前者可在本机截获数据,后者可控制网络转发环节。
- 仅保证业务服务器可信并不能保护明文链路;需要安全传输机制覆盖客户端与服务器之间的通信过程。
HTTP 使用明文传输,无法保证通信内容不被沿途节点查看或修改。 请求会经过用户电脑、WiFi 路由器和运营商等环节,只要某个节点能够转发流量,就可能窃取数据、篡改请求或伪造响应。比如客户端装有恶意软件,或者连接了钓鱼 WiFi,账号和业务数据都可能被截获。即使业务服务器可信,也不能证明整条明文链路可信,因此需要 HTTPS 保护传输过程。
浏览器安全主要划分为三大块内容:页面安全、系统安全和网络安全。前面我们用四篇文章介绍了页面安全和系统安全,也聊了浏览器和 Web 开发者是如何应对各种类型的攻击,本文是我们专栏的最后一篇,我们就接着来聊聊网络安全协议 HTTPS。
我们先从 HTTP 的明文传输的特性讲起,在上一个模块的三篇文章中我们分析过,起初设计 HTTP 协议的目的很单纯,就是为了传输超文本文件,那时候也没有太强的加密传输的数据需求,所以 HTTP 一直保持着明文传输数据的特征。但这样的话,在传输过程中的每一个环节,数据都有可能被窃取或者篡改,这也意味着你和服务器之间还可能有个中间人,你们在通信过程中的一切内容都在中间人的掌握中,如下图:

从上图可以看出,我们使用 HTTP 传输的内容很容易被中间人窃取、伪造和篡改,通常我们把这种攻击方式称为中间人攻击
具体来讲,在将 HTTP 数据提交给 TCP 层之后,数据会经过用户电脑、WiFi 路由器、运营商和目标服务器,在这中间的每个环节中,数据都有可能被窃取或篡改。比如用户电脑被黑客安装了恶意软件,那么恶意软件就能抓取和篡改所发出的 HTTP 请求的内容。或者用户一不小心连接上了 WiFi 钓鱼路由器,那么数据也都能被黑客抓取或篡改。
原理拆解: HTTP 报文进入传输链路后仍保留可读的请求行、响应头和正文。处于客户端与服务器之间、且能够转发流量的节点,不但可以复制账号、查询参数或业务数据,还可以改写请求目标、替换响应正文。这里同时缺失保密性、完整性和对通信对象的可靠认证;服务器自身可信,无法证明沿途转发者可信。
最小验证: 输入为客户端发往源站的普通 HTTP 请求,验证中间代理能够读取并修改响应。将以下代码保存为 mitm.js,使用 node mitm.js 运行,再访问 http://127.0.0.1:8080/:
const http = require('node:http');
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('balance=100');
}).listen(8081, '127.0.0.1');
http.createServer((clientReq, clientRes) => {
console.log('代理看到请求:', clientReq.method, clientReq.url);
const upstream = http.request({
hostname: '127.0.0.1',
port: 8081,
path: clientReq.url,
method: clientReq.method,
headers: clientReq.headers
}, upstreamRes => {
let body = '';
upstreamRes.setEncoding('utf8');
upstreamRes.on('data', chunk => body += chunk);
upstreamRes.on('end', () => {
clientRes.writeHead(upstreamRes.statusCode, upstreamRes.headers);
clientRes.end(body.replace('100', '0'));
});
});
clientReq.pipe(upstream);
}).listen(8080, '127.0.0.1');
关键点是代理直接获得 method、url 和响应正文,并把 balance=100 改成 balance=0;浏览器预期显示修改后的内容。该实验只模拟链路中具有转发能力的节点,不表示任意互联网主机都能截获流量。
边界与排查: HTTPS 能保护传输中的内容,却不能清除客户端恶意软件,也不能阻止已授权服务器记录明文。验证线上链路时可检查是否仍有 http:// 请求、是否发生明文重定向,并用抓包结果确认敏感正文不再以可读文本出现。
面试官追问
追问 1商品查询接口只传公开的商品编号,产品经理因此认为继续使用 HTTP 没有安全风险,你会如何反驳?
即使数据不保密,明文链路仍缺少完整性和通信对象认证,转发节点可以修改商品编号、伪造价格响应或注入内容。是否包含密码只影响泄露后果,不能消除中间人篡改,因此线上业务仍应使用正确配置的 HTTPS。
追问 2商场免费 WiFi 上出现订单金额被改写,但源站审计显示服务器未被入侵,你会优先验证哪条链路?
应优先检查客户端到源站之间是否仍存在 HTTP 请求、明文重定向或受控代理,并结合抓包确认请求与响应正文是否可读。服务器可信无法证明用户电脑、WiFi 路由器、运营商等沿途节点可信,异常可能发生在转发阶段。
追问 3公司内网接口迁移期限紧,负责人认为可信办公网络足以替代 HTTPS;网络范围变化后,这个假设会产生什么后果?
可信网络名称不能保证链路中每个节点都可信,客户端恶意软件、错误代理或其他转发节点仍可能读取和改写 HTTP。一旦接口扩展到远程办公或公共网络,暴露面还会增加;应让传输保护独立于接入网络假设。
追问 4全站已经显示锁形图标,监控却发现登录后仍有一次 http:// 跳转;你会怎样判断敏感数据是否曾明文传输?
应还原完整重定向链,检查表单提交目标、请求方法和每一跳协议,并用抓包确认敏感正文是否以可读文本出现。最终页面是 HTTPS 不代表中间步骤安全;若数据已先发往 HTTP,后续升级连接无法追回已暴露内容。
追问 5客户端已全面切换 HTTPS,安全评审能否据此关闭“本机恶意软件读取请求内容”的风险项?
不能直接关闭,HTTPS 保护的是传输链路中的内容,不会清除客户端上的恶意软件,也不能阻止已授权服务器记录解密后的数据。它能显著限制中间转发者窃听和篡改,但端点失陷仍需依靠终端与服务端安全措施处理。
# 在 HTTP 协议栈中引入安全层
30 秒速记
HTTPS不是用新应用协议替换HTTP,而是在HTTP与TCP之间增加安全层。- 发送方向由安全层加密
HTTP数据,再交给TCP;接收方向先解密,再把内容交给HTTP。 - 安全能力集中在中间层,因此上层仍按
HTTP组织消息,下层仍通过TCP/IP传输。 - 理解
HTTPS的关键是理解安全层如何建立可用的加解密能力,而不是重新解释HTTP或TCP。 - 这一结构只说明安全层的位置和基本职责;具体如何协商算法、密钥及身份可信性,还需要后续机制完成。
HTTPS 不是替换 HTTP 的新协议,而是在 HTTP 与 TCP 之间加入 TLS 安全层。 发送时,TLS 把 HTTP 数据封装并加密后交给 TCP;接收时则先校验、解密和重组,再交还给上层。应用仍然使用 GET、POST 和状态码,TCP 也仍负责可靠传输。这个分层只说明安全能力放在哪里,身份认证、密钥协商和算法选择还要由具体握手机制完成。
鉴于 HTTP 的明文传输使得传输过程毫无安全性可言,且制约了网上购物、在线转账等一系列场景应用,于是倒逼着我们要引入加密方案
从 HTTP 协议栈层面来看,我们可以在 TCP 和 HTTP 之间插入一个安全层,所有经过安全层的数据都会被加密或者解密,你可以参考下图:

从图中我们可以看出 HTTPS 并非是一个新的协议,通常 HTTP 直接和 TCP 通信,HTTPS 则先和安全层通信,然后安全层再和 TCP 层通信。也就是说 HTTPS 所有的安全核心都在安全层,它不会影响到上面的 HTTP 协议,也不会影响到下面的 TCP/IP,因此要搞清楚 HTTPS 是如何工作的,就要弄清楚安全层是怎么工作的。
总的来说,安全层有两个主要的职责:对发起 HTTP 请求的数据进行加密操作和对接收到 HTTP 的内容进行解密操作
我们知道了安全层最重要的就是加解密,那么接下来我们就利用这个安全层,一步一步实现一个从简单到复杂的 HTTPS 协议。
原理拆解: HTTPS 保留 HTTP 的方法、状态码、头部和正文语义,只把这些字节交给位于其下方的 TLS 安全层。发送时,TLS 将应用数据封装为记录并加密,再通过 TCP 发送;接收端按相反顺序校验、解密和重组,最后把恢复出的 HTTP 数据交给上层。应用仍生成 GET、POST 等消息,TCP 仍提供可靠字节流,安全层承担身份认证、密钥协商以及传输数据保护。
最小验证: 输入为 example.com 的主机名和一个 HTTP/1.1 请求,验证程序先建立并校验证书对应的 TLS 通道,再在通道中收发普通 HTTP 报文:
printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' |
openssl s_client \
-connect example.com:443 \
-servername example.com \
-verify_return_error \
-quiet
-connect 建立到 443 端口的 TCP 连接,-servername 提供证书选择所需的服务器名称,-verify_return_error 使证书校验失败时终止连接。成功时会看到 HTTP/1.1 响应行、响应头和正文,说明进入安全通道前后的应用层消息仍是 HTTP;抓取链路流量时则不应直接看到这段请求正文。执行结果受本机 OpenSSL 信任库、网络访问和服务端协议配置影响。
边界与排查: 仅在协议栈中加入加密层还不够:若不验证证书,客户端可能与攻击者协商出一条“加密但对象错误”的连接;若密钥或算法选择不安全,保密性也会下降。排查时应区分 TCP 连接失败、TLS 握手或证书失败、以及握手成功后的 HTTP 状态错误,这三类问题位于不同层。
