资讯动态

HTTPS安全原理:加密、防篡改与身份认证,解析中间人攻击

发布时间:2026/10/1 3:25:20 来源:尧图企业网站定制
很多人第一次接触HTTPS可能都听过“HTTPS比HTTP安全”这句话但真被问到“为什么安全”“它到底防住了什么”“中间人攻击又是什么”的时候往往只能答出“加密了”三个字再多就说不清了。我自己刚入行那会儿也一样甚至一度以为HTTPS就是给网页加个锁直到后来自己在公司网关抓包、搭测试环境做抓包代理、给客户排查证书报错才把这条链路真正理顺了。这篇东西我就从标题里那三件事说起——内容加密、防止篡改数据完整性、身份认证网站认证再加上中间人攻击一起来拆一拆HTTPS到底做了什么才能让数据在公网这种“人人都能路过”的环境里达到“一定程度的安全”。这里的“一定程度”很重要因为HTTPS不是万能的它有自己的边界砍掉任何一环安全都会塌方。文章会尽量把原理讲成像聊天一样顺——不堆数学公式用场景、用类比、用实际抓包经历来说明适合刚学网络协议的学生、刚接手Web服务的开发者、以及单纯想搞明白“小锁头”背后是怎么回事的普通用户。1. 为什么只说“一定程度”——先看HTTP裸奔时的三宗罪HTTPS全称是HTTP Over TLS本质就是“在HTTP外面套了一层TLS安全协议”。要理解这层壳的价值得先知道不套壳的HTTP是什么样。HTTP明文传输这件事听起来好像没什么但你在真实环境里抓一次包就会脊背发凉——浏览器的请求头、Cookie、表单数据、URL参数甚至连你输入的密码全部以可读文本的形式出现在网络链路上。我最早在办公室做协议分析的时候用抓包工具随便抓一个80端口的流量就能在报文里直接看到用户的登录名、会话ID和明文密码。我当时的第一反应是这不等于把银行卡密码写在明信片上寄出去吗是的HTTP时代基本就是这个状态。具体来说明文HTTP面临三大类风险正好对应标题里HTTPS要解决的三个能力。第一类风险窃听。数据包在网络上传输要经过你的交换机、运营商的路由器、各种网关设备链路上任何一个环节有监听设备内容就完全暴露了。不需要多高深的技术只要把网络那头接上抓包工具就能还原整个会话。这对应HTTPS的内容加密能力——让监听者拿到密文也解不开。第二类风险篡改。攻击者不仅能看还能改。数据包从A传到B的过程中中间节点可以修改包里的内容再发给接收方。比如你看到的网页是“转账给张三”攻击者可以改成“转账给李四”再继续传。接收方如果不校验完整性根本发现不了内容已经被动过手脚。这对应HTTPS的数据完整性能力——确保你收到的东西就是对方发出的东西一个字节都没被改。第三类风险伪装。你以为在跟真正的网站通信但实际跟你对话的可能是假冒的服务器。典型的场景就是钓鱼攻击配合DNS劫持——域名解析被改掉你访问“example.com”时流量被导到一个攻击者搭建的假站点上。攻击者完全可以发给浏览器一张假的“身份证”假装自己是正主。这对应HTTPS的身份认证能力——让客户端确认我现在连的这台服务器确实就是域名对应的那台服务器而不是李鬼。这三类风险恰恰就是安全领域常说的CIA三要素里的三个核心维度保密性Confidentiality、完整性Integrity、真实性Authenticity。HTTPS的设计目标就是同时通过加密、校验、证书认证来解决这三个问题缺一环都不行。这里要特别强调“一定程度”。因为HTTPS保护的是“传输通道”——它保证数据从你的浏览器到目标服务器之间这段路上的安全。它不负责保证服务器端本身安全不负责保证你的电脑有没有被装木马也不负责保证你访问的网站本身是不是个钓鱼站证书只能证明“这个域名的服务器是真实运营的”不能证明网站内容可信。理解了这个边界再看中间人攻击就清楚很多——攻击者真正要突破的就是这条“通道”。2. 内容加密TLS握手里非对称加密与对称加密的分工合作HTTPS的内容加密不是直接拿一整个大密钥把数据从头到尾加密——它是通过一次“TLS握手”先协商出一个会话密钥然后用这个会话密钥对称加密后续所有传输数据。这套机制是HTTPS的核心值得从头讲透。2.1 为什么需要两套加密算法配合对称加密比如AES的特点是“一把钥匙开一把锁”加密和解密用同一个密钥速度快适合加密大量数据。但问题来了——这把钥匙怎么安全地交给对方如果直接把密钥放在明文里传输那跟没加密一样如果先加密再传密钥那加密密钥的钥匙又怎么传这就是著名的“密钥配送问题”。非对称加密比如RSA解决了密钥传输问题。它有两个钥匙公钥和私钥。公钥可以公开发给任何人私钥自己留着。用公钥加密的数据只有对应的私钥能解开反过来用私钥加密的数据任何人都能用公钥验证。速度快慢上非对称加密比对称加密慢好几个数量级不适合用来加密大量报文但它很适合在通信开始时“传递密钥”。所以TLS的握手逻辑很清晰用非对称加密安全地协商出对称密钥再用对称密钥快速加密实际业务数据。这是全世界的密码学家摸索多年后的共同答案——各取所长组合使用。2.2 一次标准TLS握手的过程拆解我用最常见的RSA密钥交换举例子把流程简化到能看懂但又不失真客户端发起“ClientHello”告诉服务器自己支持的TLS版本、支持的加密套件列表。服务器回应“ServerHello”并下发证书服务器从客户端列表里挑一个双方都支持的加密套件然后把自己的数字证书证书里包含服务器公钥发给客户端。客户端验证证书这是身份认证的环节后面第4章专门讲。简单说客户端会用内置的CA公钥验证这张证书是不是真的、域名是否匹配、有没有过期。客户端生成“预主密钥”Pre-master Secret用服务器公钥加密后发给服务器。因为这是用公钥加密的中途即使被截获也只有持有对应私钥的服务器才能解开。服务器用自己的私钥解出预主密钥。此时双方手里都有了同一个预主密钥各自基于它派生出一组会话密钥实际会派生出多个密钥分别用于加密、完整性校验等。双方互发“Finished”消息用会话密钥加密一个握手摘要确认对方也持有相同的密钥。至此握手完成后续所有HTTP数据都走对称加密通道。这里有个细节值得注意整个握手过程中唯一真正通过公钥加密传输的“核心机密”就是第4步的预主密钥。它一旦安全抵达服务器后面双方就可以在各自本地生成一模一样的会话密钥不需要再在网络上传输密钥本身了。这就是“密钥协商”的含义——不是在传钥匙而是在“各自配出同一把锁”。2.3 ECDHE与“前向保密”这件事RSA密钥交换有个历史性缺陷后来被业界诟病了很久如果服务器的私钥泄露了或者被第三方国家力量记录后长期破解所谓“先记录后解密”那么过去所有用这个私钥协商出的会话密钥都能被还原历史流量全部暴露。这就是“缺乏前向保密”。所以现在主流推荐的是ECDHE椭圆曲线迪菲-赫尔曼密钥交换套件。它的思路完全不一样——不直接传递密钥而是双方各自生成一个临时随机数通过椭圆曲线算法在公网上交换一些公开参数最后双方能算出同一个会话密钥但攻击者即使截获了所有公开参数在计算上也无法推导出这个密钥。交换过程中各自的临时私钥用完即焚、不会长期保存即使服务器长期私钥泄露也无法倒推出历史会话密钥。ECDHE带了一个额外好处性能比RSA协商更快同样的安全强度下椭圆曲线运算量小很多。所以你在现代服务器配置里看到的推荐顺序基本都是TLS_ECDHE_开头或者TLS_AES_128_GCM_SHA256这类TLS1.3套件。做服务端安全配置时如果有老旧的RSA密钥交换套件还开着建议果断关掉。实际操作中判断一个站点用的什么协商算法很简单浏览器地址栏点开小锁头查看证书信息或者用在线工具扫描SSL配置就能看到“密钥交换: ECDHE_RSA”“加密套件: TLS_AES_256_GCM_SHA384”这类字段。3. 数据完整性加密之外更要防“聪明”的攻击者改包很多人有个误区以为数据一旦加密了自然就不会被篡改。严格来说这是个危险的误解。密文确实无法直接阅读但攻击者不需要读懂内容他只需要“改”就行——把密文中的某些字节翻转、替换甚至把一整段合法密文重放到另一个上下文里接收方解密后得到的就可能是一堆乱码或恰恰被攻击者控制过的合法明文。所以加密只解决了“偷看”不解决“改”。数据完整性的核心机制是在每条消息上附加一个“指纹认证标签”专业叫法是消息认证码MACMessage Authentication Code。它跟普通哈希摘要不是一回事——下面这个区别很多人混淆值得说清楚。3.1 摘要 vs 消息认证码差在一个“密钥”我们常听说的MD5、SHA-256这些哈希算法可以把任意长度的数据压缩成固定长度的摘要。哈希本身确实有“指纹”效果——数据变了摘要就会变。但问题在于哈希算法是公开的攻击者完全能自己算出新摘要连带替换掉原摘要。这就好比你的档案袋上贴了一张公开的封条只要知道封条长什么样谁都能伪造一张贴上去。消息认证码MAC不一样。它是在计算指纹时掺入了双方才知道的会话密钥输入的公式是“密钥数据”一起做哈希运算。不知道这把密钥的人哪怕看到了数据和MAC值也伪造不出一个合法的MAC。服务器收到密文后先解密再用自己手里的密钥重算一遍MAC如果跟消息里附带的MAC不一致就说明消息在途中被动过手脚——直接丢弃。这就好比你给档案袋贴的封条是用一个别人看不见的特殊印章盖的伪造不了。3.2 TLS记录层的“先校验后信任”TLS对每条应用数据都做这层保护发送方会把“序列号 消息内容 密钥”一起算出一个MAC附在每条记录后面接收方逐条校验校验不过就整条丢弃并中断会话。序列号的作用也很关键——它防止攻击者把某条旧消息重新发给服务器重放攻击因为对不上号校验就会失败。这里聊一个现代TLS的演进TLS 1.3基本上已经全面转向AEAD认证加密套件比如AES-GCM。AEAD的精妙之处在于把“加密”和“完整性认证”合并成同一步完成——加密算法直接在计算过程中生成认证标签解密时如果标签校验失败根本不会把明文输出给你。既有安全性优势也有性能优势。你在配置里看到的“AES_128_GCM”里的GCM就是这个机制。我当年第一次怀疑“加密了还被篡改”这个概念是在调试一个流媒体播放器的HLS协议时。我们用AES加密了分片但播放器经常出现画面花块。排查后发现问题不是解密失败而是有个缓存节点在转发时偶尔丢了几字节导致密文错位解密出来的内容面目全非但没被即时发现。后来在协议层补了完整性校验现象立刻消失。这让我印象很深——完整性和加密是两回事缺一不可。4. 身份认证“你怎么确定对方是真的”——证书链与CA信任前面两章讲的都是“就算有人偷看也看不懂、就算有人改包也改不了”但你有没有想过一个问题如果站在你面前的服务器本身就是冒牌货呢这一步安全就追不上你了。比如攻击者在公共WiFi环境里搭一台伪装的服务器把你的请求全部劫到它那儿。你正常发起TLS握手它正常回一个“证书”——如果客户端不加验证地接受那它就能拿到你的加密内容并解密再转发给真正的服务器造成神不知鬼不觉的中间人攻击。所以身份认证这一环是HTTPS安全三大支柱的地基。没有它加密和完整性全部形同虚设。这就要说到数字证书和CA体系。4.1 证书里藏了什么一个“数字签名”如何锁死身份服务器在握手下发的所谓“证书”本质就是一张经过权威机构背书的电子身份卡。里面包含几个关键字段所属域名、证书持有者信息、公钥、有效期、CA签名等信息。来捋一捋逻辑链某公司申请证书时CA会验证这家公司确实拥有example.com这个域名或验证它是企业实体然后生成一张证书并用CA自己的私钥对证书内容做一次签名——这个签名就是“背书”。浏览器里预装了各大CA的根证书含CA公钥浏览器拿到服务器证书后用CA的公钥去验证签名是否匹配。只要签名匹配就能确信这张证书确实是CA签发过、而且内容没有被篡改过。证书里绑定了域名浏览器检查当前访问的域名和证书里的域名一致。域名对不上也会报错。整个过程最底层的逻辑就一句话信任是可以传递的——我信任CACA担保了这个域名所以我信任这个域名。这就是PKI公开密钥基础设施的本质。你不需要提前认识每一个网站你只需要信任少数几个根CA它们替你做了背书。4.2 证书链为什么你的根证书不能直接给人家签名实际操作中你会发现服务器下发的通常不止一张证书而是一个“证书链”服务器证书叶子证书→ 中间证书 → 根证书。为什么要有中间的环节因为根证书太宝贵了根CA的私钥一旦泄露整个信任体系就崩了。所以根CA极少拿自己的私钥直接给最终用户签证书而是签发一批“中间CA证书”再由中间CA给企业签。企业证书升级、吊销、续期时根证书几乎不用动。这样风险被隔离在中间层。浏览器在验证时会沿证书链一步步回溯用中间证书的密钥验证叶子证书用根证书的密钥验证中间证书直到链顶的根证书命中浏览器预装的信任锚。现实中很多“证书报错”的根源就在这条链上一些新手部署HTTPS只上传了叶子证书没把中间证书一起传导致手机浏览器和某些严格校验的客户端无法回溯到根证书就会报“证书链不完整”“unable to get local issuer certificate”。我帮人排查过好几回一半以上都是这个问题。解决方法是把“叶子证书 中间证书”按顺序拼接成一个文件一起配置到服务器Nginx里就是ssl_certificate指令引用那个合并后的pem文件。4.3 证书级别DV、OV、EV之间差了什么这里顺便科普一下证书验证级别的差异。DV证书域名验证只验证你有没有域名的控制权——能收到验证邮件或者能放一条特殊的DNS记录就算数个人就能申请成本低。OV证书组织验证会额外验证申请主体的企业信息。EV证书扩展验证审核最严格会线下核实企业法律存在性浏览器地址栏会显示绿色公司名。很多人会问我该选哪种我的建议是个人项目或测试环境DV够用企业官网和交易类站点至少上OV如果品牌背书是核心诉求才考虑EV。但从纯技术安全角度看DV和EV在加密强度上没有任何区别——它们提供的是“信任等级”的差异不是“加密等级”的差异。Web应用真正的安全短板往往在应用层逻辑而不是证书验到哪个级别。4.4 浏览器如何发现“假证书”——以及它发现不了的场景现代浏览器对证书的检查比想象中严格域名匹配、有效期、签名链、证书吊销状态通过OCSP或CRL查询、证书透明度日志、以及算法强度不再接受SHA-1签名的证书都会看。任何一项不合格浏览器都会阻断访问并给出一个清晰的警告页——“您的连接不是私密连接”。但“发现不了假证书”也不是不存在。历史上多次出过事CA被骗签发了一张合法伪造的域名证书或者攻击者直接入侵了CA。这说明CA体系本身是有信任风险的——它依赖CA的道德和能力。后来推出的“证书透明度”CT机制要求所有CA签发的证书都要公开记录在日志里浏览器会额外检查这张证书有没有出现在日志中这在一定程度上约束了CA不敢乱签、也无法悄悄签。所以你看身份认证这一环并不完美它在实践中不断打补丁但整体思路是清晰且可靠的通过CA的背书让客户端能验证“服务器的身份声明”是不是真的。既然你相信这个验证是有效的那你就把协商密钥的安全建立在服务器公钥上——这就是整个通道信任的起点。5. 中间人攻击专门穿HTTPS“凯甲”的技术到底是怎么得手的中间人攻击Man-in-the-middle attackMITM是跟HTTPS最密切相关的威胁之一。很多人一听到这个词就以为“攻击者是不是能破解我的HTTPS加密”而真相是——攻击者通常根本不去破解加密算法他选择骗过你的客户端让你以为你连接的是目标服务器实际上连接的却是他。5.1 一场典型MITM的完整剧本拿公共WiFi场景举例攻击者可以在接入点或路由器层面做手脚截获你的所有流量。假设你要访问pay.example.com你的浏览器发起TLS握手请求这个请求先到达了攻击者的代理服务器。攻击者自己跑到pay.example.com建立起另一条真正的HTTPS连接。此时他相当于你的“代理”他替你访问目标站也替目标站接待你。关键点在第一步你的浏览器发出的握手请求收到的是攻击者伪造的证书。如果浏览器验证通过——注意这通常是因为攻击者在自己设备上装了一个被浏览器信任的伪CA比如企业网管或恶意软件装的又或者用户在警告页上点了“继续访问”——那么TLS握手就会在“你 ↔ 攻击者”之间成功建立。此后你发给网站的密文攻击者用自己的密钥解开看清楚明文内容重新用他跟目标服务器的会话密钥加密再转给真正的网站。反之亦然。你完全感知不到异常因为通信表面上是通的。这就是“中间人”这个词的形象来源——他站在中间同时扮演你的“服务器”和服务器眼中的“客户端”整条通信里的所有数据他都能看、能记、能改。5.2 为什么证书验证是阻断MITM的核心关口捋一下你会发现攻击者最难的不是截获流量——那个简单最难的只有一件事让客户端信任他伪造的证书。没有这一步TLS握手第一步就失败浏览器会直接终止连接。所以正常的用户设备攻击者伪造的证书会被浏览器拦下来MITM在这里就断了一旦攻击者能让你的设备信任他那个伪CA比如诱导你安装描述文件、利用系统漏洞植入根证书、或者接管你正在用的企业证书体系那MITM就能成立。这也是为什么安全圈一直强调“不要随便信任和安装未知来源的根证书”——那是通往整个信任体系的钥匙钥匙丢给坏人了加密再强也白搭。企业网的HTTPS流量审计比如安全网关解密看内鬼走的也是这个思路企业设备预装公司CA证书所有员工流量流量都被这个CA动态签发虚拟证书网关得以解密检查后重新加密再转发。这也是MITM技术形态的合法应用——技术是中性的关键在于谁持有了信任根。5.3 SSL剥离比伪造证书更狡猾的降级攻击还有一种不碰证书的MITM变种叫SSL剥离SSL Stripping非常经典。思路是在用户发起HTTPS请求之前动手脚。比如攻击者劫持了HTTP流量把一个跳转链接里的“https://”悄悄改成“http://”或者抢在你和网站完成握手之前拦截通讯让后续所有数据在HTTP明文下传输。因为你的浏览器可能根本没有发起过TLS握手自然不会有证书警告。要防护这种攻击一个关键的现代Web安全机制是HSTSHTTP严格传输安全——服务器通过响应头告诉浏览器“未来一段时间内访问我这个域名只准走HTTPS一旦发现HTTP跳转浏览器自己主动拒绝。”这样即使用户手动输入的是http://浏览器也会自动升级为https://不给剥离留机会。我自己的站点上线HTTPS后做的第一件事就是加HSTS头。5.4 实操视角当“合法”的抓包工具也是MITM说到MITM很多人还会想那我在电脑上用的抓包工具比如Charles、Fiddler、Wireshark配合SSLKEYLOGFILE怎么就能看到HTTPS明文呢其实这正好帮我理解了这个机制——你主动在系统里安装了抓包工具的根证书就等于把自己交给了一个“受信任的中间人”。抓包工具替你建立与服务器的HTTPS连接又用自己生成的证书跟你建立连接两个连接在你和服务器之间“翻译”内容。你之所以能看明文是因为你是中间人这端——你授权它成为你的代理。这个案例屡次在我面试或带新人的时候提到因为它直观地证明了没有合适的信任前提谁也别想看穿加密通道一旦信任前提被突破加密通道就变成透明通道。而“信任前提”这东西正是PKI体系里最值得反复琢磨的软肋。6. 落地部署与实操体会把HTTPS真正“用对”的几个坑前面的内容偏原理最后我分享一些自己实际部署HTTPS过程中踩过的坑、或者认为对正在动手配置的人最有用的经验。这些细节看起来小漏掉一个都可能让安全的防线出现缝。6.1 证书链不完整是移动端报错的头号原因一套“完整”的Nginx配置通常长这样server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/ssl/fullchain.pem; # 叶子证书中间证书拼接 ssl_certificate_key /etc/nginx/ssl/example.com.key; # 私钥 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; }很多从证书商拿到的下载包会分成三个文件证书本体cert、中间证书chain/ca bundle、私钥key。如果你只把cert填进ssl_certificatePC端浏览器可能还能访问因为浏览器做了中间证书自动补齐但Android端的严格校验就会直接报“NET::ERR_CERT_AUTHORITY_INVALID”。正确做法是把cert和chain拼起来cat example.com.crt intermediate.crt fullchain.pem6.2 混合内容Mixed Content成了现代的“半裸奔”站点上线HTTPS后如果页面里还引用了http://开头的图片、脚本或接口就产生了“混合内容”。其中脚本和iframe属于高危——因为浏览器虽然页面是HTTPS但对这类资源还是可能用HTTP去拉取攻击者就有机会在中间篡改脚本。现代浏览器对高风险混合内容直接默认不加载低风险资源图片则打一个警告标。对开发者来说根治方案是页面内所有资源都用相对路径或保持https协议多一步部署完HTTPS后养成习惯F12控制台看有没有mixed content警告。6.3 算法与版本别把兼容性当借口老一些的部署指南还在推荐TLSv1.0、TLSv1.1但2024年这个时间点上TLS1.0和1.1已经正式废弃多年主流浏览器默认都不支持了。如果服务器还在开着这两个版本意义只是“兼容老古董”安全隐患却实打实存在比如POODLE、BEAST等攻击向量。我的建议是直接只开TLSv1.2和TLSv1.3密码套件优先走AEAD类。如果担心兼容性真的有痛点用一份基础配置先跑起来再去老设备上验证不要怕“高级配置导致连不上”——现代生态基本不会了。6.4 开HSTS之前想清楚一件事HSTS是我很推荐开的但有个细节容易被忽略HSTS一旦生效浏览器在生效期内不允许你回退到HTTP哪怕证书配置坏了用户也无法通过手动绕过强制跳转。所以顺序应该是先确保HTTPS配置长期稳定无误跑一两个星期再开HSTS且先设一个比较短的max-age比如300秒确认无误后逐渐加长到一年31536000。如果设成一年后反悔在Chrome里“强制刷新”也救不回来得等过期或手动清理站点数据。6.5 自己签发证书、自用场景下的“为什么会被拦”开发和测试环境里很多人图省事自己用OpenSSL签发一张自签名证书结果浏览器疯狂报警告于是心里很烦。其实这个警告是正确的——自签名的证书没有权威CA的背书跟“伪造证书”在形式层面是同源的。解决办法很简单把这张自签名证书导入到测试设备系统的信任根列表里只适合本机/小范围测试或者干脆本地跑个CA用这个小CA签证书再导入信任比如用mkcert这个小工具一条命令搞定本地HTTPS环境。我自己开发时的做法就是mkcert既不用买证书又能让浏览器完全信任调试体验很舒服。写在最后安全的边界永远在人这一端把这套东西串起来再看HTTPS你会发现它本质上是一套“身份验证 → 密钥协商 → 加密通信 → 完整性自检”的组合拳CA签名负责让你信得过对面的人非对称加密负责把只有你们俩知道的密钥安全地发过去对称加密负责高效传输内容MAC负责拦截任何偷偷改动过的数据。每一环都互相咬合缺一个整条锁链就废了。我个人实际使用中最大的体感是搞懂了这套机制之后再看到地址栏那个小锁头心里的感觉完全不同——它不是“绝对安全”的保证书而是“这条连接走完了标准认证和加密流程”的一个信号。你在网上的一切行为最终的安全都建立在一个问题上你信不信任那个替你签字的CA以及你有没有把不该信任的东西比如来路不明的根证书装进自己的信任列表。这也呼应了标题里“一定程度”这四个字——技术帮我们把安全基线提到很高但最后那张信任的门禁卡在人自己兜里。明白这一点你就算真正理解HTTPS了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑