OSI 模型共有七层,从下到上分别是物理层、数据链路层、网络层、运输层、会话层、表示层和应用层
于是简化层次:
应用层(会话层、表示层和应用层):http https FTP, TFTP, DNS,
传输层:tcp/udp
网络层:ip
网络接口层:(物理层、数据链路层、)
预检请求相关:
不触发:get、post、head;content-type:非application/json;请求头header未使用未定义字段
若触发:
浏览器发送options方法,请求头携带: origin、access-control-request-method、access-control-request-headers
返回:
access-control-allow-origin、access-control-allow-methods、access-control-allow-headers
若不在服务器范围内则不发送请求,且控制台报错。
HTTPS的加密与解密:
需要知道的知识前提:
A与B两人,B生成一对公钥与私钥。
B将自己的公钥传给A,A用B给的公钥对自己的内容进行加密后,再传给B。B再用自己的私钥进行解密
当A对自己的内容加密后,如果自己的原始内容丢失,只有加密后的内容,如果没有B给自己私钥,自己也无法解密
于是将A与B的身份带入到浏览器与服务器。A就是浏览器,B就是服务器。
以浏览器请求服务器的一个网址为例子:
浏览器发送请求后,服务器会向浏览器提供一个CA证书(第三方认证的机构,以证实访问服务器的真实性),证书携带了一个公钥
浏览器确认了服务器的身份后,就使用服务器提供的公钥、以及浏览器自己随机生成的密钥,浏览器生成的密钥作为会话密钥。使用服务器的公钥对浏览器生成的密钥进行加密,然后浏览器将加密过后的会话密钥发送给服务器。后续就使用这个会话密钥进行通信交流,有且只有服务器使用自己的私钥才能解密获得浏览器生成的密钥。
此时浏览器与服务器双方都能够对各自的内容进行加密传输,但此时衍生了另一个问题:中间的内容虽然不能被解密,但是可能会被遭到黑客拦截篡改。此时引入了另一个东西:生成消息认证码 (MAC)-防止篡改的关键
浏览器会使用自己的会话密钥对数据进行加密,这是为了保密。为了防止消息被篡改,浏览器将原始数据使用会话密钥以及约定的哈希算法对内容进行加密,为原始数据生成一个“摘要”或“签名”,这个东西就叫消息认证码 (MAC)。随后浏览器将加密后的数据以及MAC发送给服务器
服务器收到消息后,使用会话密钥进行解密数据,然后再将原始数据使用会话密钥以及约定的哈希算法进行加密得到MAC,随后再将两个MAC进行对比,若两者相同才能确认数据没有被篡改。
服务器返回页面的过程则同理
AI总结版:
HTTPS的加密与解密
需要知道的知识前提:非对称加密
- A与B两人,服务器B有一对钥匙:公钥和私钥。
- B把公钥给了很多人,包括A。但私钥只有B自己有。
- A想给B发送一个秘密盒子,就用B的公钥把盒子锁上。
- 这个被公钥锁上的盒子,只有用B的私钥才能打开。即使是A自己,一旦锁上后也打不开了。这样就保证了只有B能看到盒子里面的东西。
第一阶段:握手——安全地交换“暗号”(会话密钥)
现在,A是浏览器,B是服务器。
- 浏览器向服务器打招呼:“你好,我们来建个安全连接吧!”
- 服务器回应,并递给浏览器一个证书。这个证书由权威的CA机构颁发,里面包含了:
- 服务器的身份信息。
- 服务器的公钥。
- 浏览器验证证书的真伪(就像检查身份证),确认对方是货真价实的服务器,而不是骗子。
- 浏览器生成一个随机的、本次通信专用的“暗号”,我们称之为会话密钥。
- 为了把这个“暗号”安全地告诉服务器,浏览器用服务器的公钥将它锁起来(加密),然后发给服务器。
- 服务器收到后,用自己的私钥解密,也得到了这个会话密钥。
至此,握手完成。现在浏览器和服务器双方都拥有了同一个、只有他们自己知道的“暗号”(会话密钥)。后续的所有通信都用这个“暗号”进行对称加密。
第二阶段:数据传输——用“暗号”加密并防止篡改
现在浏览器和服务器之间传输的所有内容,都同时做了两件事:加密和完整性保护。
假设浏览器要发送数据 “hello”:
- 加密(防窃听):浏览器使用会话密钥对 “hello” 进行加密,得到一串乱码,比如 “Cipher(hello)”。
- 生成MAC(防篡改):浏览器使用会话密钥和原始数据 “hello” 一起进行哈希运算,生成一个独一无二的“指纹”,即消息认证码(MAC)。这个MAC就像一个盖了章的封条。
- 发送:浏览器将【加密后的数据】和【MAC封条】一起发送给服务器。
服务器收到后:
- 解密:服务器使用相同的会话密钥解密 “Cipher(hello)”,得到原始数据 “hello”。
- 验证:服务器用自己手里的会话密钥和解密出的 “hello”,用同样的算法重新计算一个MAC。
- 比对:将自己计算出的新MAC与浏览器发来的旧MAC进行比对。
- 如果一致,说明数据是完整的、未经篡改的,可以信任。
- 如果不一致,说明数据在路上被动了手脚,立刻丢弃,连接中断。
服务器返回页面的过程则同理。
一、 什么是 HTTP 协议?—— 信息在互联网上的“裸奔”
HTTP (HyperText Transfer Protocol),即超文本传输协议,是互联网上浏览器和服务器之间沟通的“通用语言”。
- 工作方式: 客户端(你的浏览器)发送一个“请求”(比如“给我看这个网页”),服务器返回一个“响应”(网页内容)。
- 核心问题: 明文传输。所有数据,包括用户名、密码、信用卡号,都像明信片一样在网络上传输,没有任何加密。
这导致了三个致命风险:
- 窃听风险: 中间人可以轻易偷看你的所有信息。
- 篡改风险: 中间人可以修改网页内容,植入广告或病毒。
- 冒充风险: 你无法确认你访问的网站就是你以为的那个,很容易被“钓鱼网站”欺骗。
二、 HTTPS 如何解决问题?—— 为信息穿上“安全盔甲”
HTTPS (HTTP Secure) 并非一个新协议,它的本质是 HTTPS = HTTP + SSL/TLS。它在HTTP下面增加了一个安全层(SSL/TLS),专门负责加密和身份认证,从而解决了HTTP的所有安全问题。
| 特性 | HTTP | HTTPS |
|---|---|---|
| 安全性 | 明文传输,不安全 | 使用 SSL/TLS 加密,安全 |
| URL 与端口 | http://,默认 80 |
https://,默认 443 |
| 证书 | 不需要 | 必须有由权威机构(CA)颁发的数字证书 |
| 浏览器显示 | 地址栏显示“不安全” | 地址栏显示安全锁标志 |
三、 HTTPS 的核心:SSL/TLS 握手详解 (The Real Deal)
在真正传输网页内容之前,浏览器和服务器必须通过一个名为“握手” (Handshake) 的复杂过程,来完成两件大事:
- 验证身份:确认对方是真家伙,不是冒牌货。
- 协商密钥:安全地商量出一个只有“你”和“我”知道的密码,用于后续的通信加密。
这个过程非常精妙,结合了非对称加密(慢,但适合交换秘密)和对称加密(快,适合大量数据传输)。以下是详细的“四次握手”步骤:
第一次握手:客户端问候 (Client Hello)
你的浏览器会向服务器发送第一条消息,里面包含:
- 支持的协议版本:比如“我最高支持 TLS 1.3”。
- 一个客户端随机数 (
Client Random):我们称之为随机数1。 - 支持的加密套件列表:一个长长的列表,告诉服务器“我会这些加密算法,你看看用哪个?”。
第二次握手:服务器回应与出示身份 (Server Hello & Certificate)
服务器收到后,会回复一条消息,里面包含:
- 确认协议版本和加密算法:从客户端的列表里选一个自己也支持的,并说“好的,我们就用这个了”。
- 一个服务器随机数 (
Server Random):我们称之为随机数2。 - 服务器的数字证书:这是最重要的部分,相当于服务器的“身份证+公钥”。
第三次握手:客户端验证并交换密钥原材料 (Client Verification & Key Exchange)
客户端收到服务器的回应后,会做几件关键的事:
- 验证证书:检查服务器的“身份证”是不是由权威机构颁发的、有没有过期、是不是发给这个网站的。如果验证失败,浏览器会弹出“不安全”的警告。
- 生成第三个随机数:验证通过后,客户端会生成一个至关重要的随机数,称为“预主密钥 (Pre-Master Secret)”。这是随机数3,也是后续“会话密钥”的核心原材料。
- 加密并发送:客户端用从服务器证书里获取的公钥,将这个预主密钥加密,然后发送给服务器。同时,它还会发送一个握手过程的校验值 (hash),证明之前的对话没被篡改。
第四次握手:服务器确认并生成最终密钥 (Server Confirmation & Key Generation)
服务器收到客户端发来的信息后:
- 解密预主密钥:用自己的私钥解密,得到只有它和客户端才知道的预主密钥(随机数3)。
- 生成会话密钥:现在,客户端和服务器同时拥有了三个相同的号码:随机数1、随机数2、随机数3。它们会使用之前商量好的算法,将这三个数混合在一起,“烹饪”出最终用于通信的会话密钥 (Session Key)。
- 最后确认:服务器也会发送一个自己计算的握手过程校验值 (hash)给客户端验证。
至此,握手阶段结束! 双方都已确认了对方的身份,并拥有了一把完全相同、绝对私密、一次性的会话密钥。整个握手过程的安全性由非对称加密和证书体系来保证。
四、 握手之后:真正的安全加密通信
握手这个复杂的过程,就是为了安全地生成那把“会话密钥”。一旦密钥在手,后续所有的通信都会变得既快速又安全。
-
客户端发送加密请求:
- 加密: 浏览器要发送请求(比如
GET /index.html),会用会话密钥通过对称加密算法(如AES)将其加密成一堆乱码。 - 生成摘要 (MAC): 为了防止数据被篡改,浏览器还会为原始请求生成一个“消息认证码”(就像一个数字指纹),并附加在加密数据后面。
- 发送: 将“加密后的数据 + MAC指纹”一起发送给服务器。
- 加密: 浏览器要发送请求(比如
-
服务器解密并验证:
- 解密: 服务器收到后,用同一个会话密钥解密数据,得到原始请求。
- 验证: 服务器会为解密后的数据重新计算一遍MAC指纹,并与收到的指纹进行比对。如果一致,说明数据在途中未被篡改;如果不一致,则立即丢弃。
-
服务器发送加密响应:
- 服务器返回网页内容时,会重复上述过程:用会话密钥加密数据,生成MAC指纹,然后一起发给客户端。客户端收到后也进行同样的解密和验证。
这个阶段,由于使用的是计算速度极快的对称加密,所以即使所有数据都经过了加密解密,用户也几乎感觉不到性能上的延迟。
总结
现在,我们可以把整个流程串起来了:
- HTTP: 裸奔通信,极不安全。
- HTTPS:
- 握手阶段 (准备工作): 通过一个复杂的“四次握手”,利用非对称加密和数字证书,安全地完成了身份验证,并让通信双方共同生成了一把对称加密用的会话密钥。这个过程还通过
hash校验确保了自身不被篡改。 - 通信阶段 (正式工作): 双方使用这把会话密钥,通过快速的对称加密来加密所有传输的实际内容(网页、图片等),并用MAC摘要来保证数据不被中途修改。
- 握手阶段 (准备工作): 通过一个复杂的“四次握手”,利用非对称加密和数字证书,安全地完成了身份验证,并让通信双方共同生成了一把对称加密用的会话密钥。这个过程还通过
接下来继续用“打电话”和“挂电话”的生动比喻,把每一步对应的客户端和服务器的状态都清晰地标注出来。彻底讲清楚整个流程。
初始状态
- 服务器 (朋友): 打开手机,等着电话进来。 ->
LISTEN(监听状态) - 客户端 (你): 手机在口袋里,啥也没干。 ->
CLOSED(关闭状态)
第一部分:三次握手 (建立连接)
目标:建立一个可靠的双向通话
| 步骤 | 动作 (技术术语) | “打电话”的比喻 | 客户端状态 | 服务器状态 |
|---|---|---|---|---|
| 1 | 客户端发送 SYN |
你拨通电话:“喂,能听到吗?” | CLOSED -> SYN_SENT (已发送同步信号) |
LISTEN |
| 2 | 服务器收到 SYN, 发送 SYN+ACK |
朋友听到并回复:“听到了,你能听到我吗?” | SYN_SENT |
LISTEN -> SYN_RCVD (已收到同步信号) |
| 3 | 客户端收到 SYN+ACK, 发送 ACK |
你听到并回复:“能!” | SYN_SENT -> ESTABLISHED (连接已建立) |
SYN_RCVD |
| 4 | 服务器收到 ACK |
朋友听到你的“能!”。通话正式开始。 | ESTABLISHED |
SYN_RCVD -> ESTABLISHED (连接已建立) |
握手完成时,双方都进入了 ESTABLISHED 状态,可以开始自由地传输数据了。
第二部分:四次挥手 (断开连接)
目标:优雅地、确保没有数据丢失地结束通话 (我们假设这次还是由 客户端 主动发起挂断)
| 步骤 | 动作 (技术术语) | “挂电话”的比喻 | 主动方 (客户端) 状态 | 被动方 (服务器) 状态 |
|---|---|---|---|---|
| 1 | 客户端发送 FIN |
你说:“我说完了,准备挂了。” | ESTABLISHED -> FIN_WAIT_1 (等待确认和对方的结束信号) |
ESTABLISHED |
| 2 | 服务器收到 FIN, 发送 ACK |
朋友说:“知道了,等我说完最后一句。” | FIN_WAIT_1 |
ESTABLISHED -> CLOSE_WAIT (等待自己关闭) |
| 3 | 客户端收到服务器的 ACK 后… |
FIN_WAIT_1 -> FIN_WAIT_2 (只等对方的结束信号了) |
CLOSE_WAIT |
|
| 4 | 服务器处理完数据后… 服务器发送 FIN |
朋友说完了,对你说:“我也说完了。” | FIN_WAIT_2 |
CLOSE_WAIT -> LAST_ACK (等待最后的确认) |
| 5 | 客户端收到 FIN, 发送 ACK |
你说:“好的,拜拜!” | FIN_WAIT_2 -> TIME_WAIT (等待足够时间以确保对方收到) |
LAST_ACK |
| 6 | 服务器收到 ACK |
朋友收到你的“拜拜”,放心地挂了电话。 | TIME_WAIT |
LAST_ACK -> CLOSED (已关闭) |
| 7 | 客户端等待 2MSL 时间后… | 你等了一会儿,确认没问题,也挂了电话。 | TIME_WAIT -> CLOSED (已关闭) |
CLOSED |
挥手完成时,双方最终都回到了 CLOSED 状态。
状态记忆小贴士
LISTEN: 服务器专属的“迎客”状态。SYN_SENT/SYN_RCVD: 名字里带SYN的,肯定是握手阶段。SENT是发送方,RCVD是接收方。ESTABLISHED: 双方最开心的状态,可以自由通信。FIN_WAIT_1/FIN_WAIT_2: 主动关闭方(先说再见的人)的状态。1表示还在等对方的ACK,2表示ACK收到了,只等对方的FIN。CLOSE_WAIT: 被动关闭方(后说再见的人)最经典的状态。意思是“我知道你要走了,但请等等我,我还没准备好关闭”。LAST_ACK: 被动关闭方发送完FIN之后的状态,等待最后一个ACK。TIME_WAIT: 主动关闭方发送完最后一个ACK之后的状态,为了网络可靠性而做的最后“保险等待”。记住:谁先提分手,谁就要TIME_WAIT。

评论(1)