Update HTTP.md
重新绘制配图,补充 TLS 握手、HTTP/3、WebSocket、跨域、单点登录与 OAuth 2.0、强缓存与协商缓存和常见状态码,更新内容编码等描述。
@@ -36,9 +36,12 @@
|
||||
* [多部分对象集合](#多部分对象集合)
|
||||
* [虚拟主机](#虚拟主机)
|
||||
* [通信数据转发](#通信数据转发)
|
||||
* [WebSocket](#websocket)
|
||||
* [跨域](#跨域)
|
||||
* [六、HTTPS](#六https)
|
||||
* [加密](#加密)
|
||||
* [认证](#认证)
|
||||
* [TLS 握手](#tls-握手)
|
||||
* [完整性保护](#完整性保护)
|
||||
* [HTTPS 的缺点](#https-的缺点)
|
||||
* [七、HTTP/2.0](#七http20)
|
||||
@@ -46,6 +49,7 @@
|
||||
* [二进制分帧层](#二进制分帧层)
|
||||
* [服务端推送](#服务端推送)
|
||||
* [首部压缩](#首部压缩)
|
||||
* [HTTP/3](#http3)
|
||||
* [八、HTTP/1.1 新特性](#八http11-新特性)
|
||||
* [九、GET 和 POST 比较](#九get-和-post-比较)
|
||||
* [作用](#作用)
|
||||
@@ -69,7 +73,7 @@
|
||||
- 第一行是包含了请求方法、URL、协议版本;
|
||||
- 接下来的多行都是请求首部 Header,每个首部都有一个首部名称,以及对应的值。
|
||||
- 一个空行用来分隔首部和内容主体 Body
|
||||
- 最后是请求的内容主体
|
||||
- 最后是请求的内容主体,GET 请求通常没有主体,POST 请求的表单数据、JSON 放在这里
|
||||
|
||||
```http
|
||||
GET http://www.example.com/ HTTP/1.1
|
||||
@@ -84,7 +88,6 @@ Proxy-Connection: keep-alive
|
||||
Upgrade-Insecure-Requests: 1
|
||||
User-Agent: Mozilla/5.0 xxx
|
||||
|
||||
param1=1¶m2=2
|
||||
```
|
||||
|
||||
响应报文结构:
|
||||
@@ -218,7 +221,7 @@ DELETE /file.html HTTP/1.1
|
||||
CONNECT www.example.com:443 HTTP/1.1
|
||||
```
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/dc00f70e-c5c8-4d20-baf1-2d70014a97e3.jpg" width=""/> </div><br>
|
||||
<div align="center"> <img src="pics/http-connect.png" width="740px"/> </div><br>
|
||||
|
||||
### TRACE
|
||||
|
||||
@@ -270,6 +273,8 @@ CONNECT www.example.com:443 HTTP/1.1
|
||||
|
||||
- **307 Temporary Redirect** :临时重定向,与 302 的含义类似,但是 307 要求浏览器不会把重定向请求的 POST 方法改成 GET 方法。
|
||||
|
||||
- **308 Permanent Redirect** :永久重定向,与 301 的含义类似,但不允许改变请求方法。
|
||||
|
||||
### 4XX 客户端错误
|
||||
|
||||
- **400 Bad Request** :请求报文中存在语法错误。
|
||||
@@ -280,12 +285,20 @@ CONNECT www.example.com:443 HTTP/1.1
|
||||
|
||||
- **404 Not Found**
|
||||
|
||||
- **429 Too Many Requests** :请求太频繁,被限流,可以在 Retry-After 首部中告诉客户端多久之后再试。
|
||||
|
||||
### 5XX 服务器错误
|
||||
|
||||
- **500 Internal Server Error** :服务器正在执行请求时发生错误。
|
||||
|
||||
- **502 Bad Gateway** :作为网关或代理的服务器从上游服务器收到了无效的响应,例如 Nginx 连不上后端,或者后端在返回响应之前断开了连接。
|
||||
|
||||
- **503 Service Unavailable** :服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
|
||||
|
||||
- **504 Gateway Timeout** :作为网关或代理的服务器没有及时收到上游服务器的响应,例如 Nginx 等待后端的时间超过了 proxy_read_timeout(默认 60 秒)。
|
||||
|
||||
502 和 504 都说明问题出在网关后面的服务上:502 是后端出错或者不可达,504 是后端太慢,排查时先看网关的错误日志,再看对应时间后端的日志和耗时。
|
||||
|
||||
## 四、HTTP 首部
|
||||
|
||||
有 4 种类型的首部字段:通用首部字段、请求首部字段、响应首部字段和实体首部字段。
|
||||
@@ -363,7 +376,7 @@ CONNECT www.example.com:443 HTTP/1.1
|
||||
|
||||
### 连接管理
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/HTTP1_x_Connections.png" width="800"/> </div><br>
|
||||
<div align="center"> <img src="pics/http-connections.png" width="760px"/> </div><br>
|
||||
|
||||
#### 1. 短连接与长连接
|
||||
|
||||
@@ -456,6 +469,8 @@ Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
|
||||
|
||||
标记为 Secure 的 Cookie 只能通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。
|
||||
|
||||
SameSite 属性控制跨站请求是否携带 Cookie,用于防范跨站请求伪造,见 [设置 Cookie 的 SameSite 属性](攻击技术.md#3-设置-cookie-的-samesite-属性)。
|
||||
|
||||
#### 8. Session
|
||||
|
||||
除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端,存储在服务器端的信息更加安全。
|
||||
@@ -515,6 +530,56 @@ JWT 与 Session 的区别:
|
||||
|
||||
JWT 只是令牌的格式,而 OAuth 2.0 是授权框架,规定第三方应用如何获得访问令牌,这个访问令牌可以用 JWT 表示。
|
||||
|
||||
#### 12. 单点登录与 OAuth 2.0
|
||||
|
||||
单点登录(Single Sign-On, SSO)指的是在一个地方登录后,访问同一家公司的多个系统都不需要再登录。
|
||||
|
||||
多个系统在同一个父域名下时(a.example.com、b.example.com),把会话的 Cookie 设置为 Domain=example.com 就能共享。域名不同时(shop.com、pay.com),Cookie 无法跨域,需要一个统一的认证中心 sso.example.com:
|
||||
|
||||
1. 用户访问 pay.com,pay.com 发现没有会话,重定向到 sso.example.com/login?redirect=https://pay.com/;
|
||||
2. 用户之前在 shop.com 登录时已经在认证中心登录过,认证中心的域名下有它自己的 Cookie,于是不需要输入密码,直接生成一个一次性的票据,重定向回 https://pay.com/?ticket=ST-1024;
|
||||
3. pay.com 的后端拿票据向认证中心验证,得到用户信息后建立 pay.com 自己的会话。
|
||||
|
||||
票据经过浏览器的地址栏,可能被记录或截获,所以只能使用一次、有效期很短,并且必须由后端去认证中心验证,而不是直接信任。
|
||||
|
||||
OAuth 2.0 解决的是另一个问题:授权第三方应用访问用户在某个服务上的数据,而不把密码交给它,例如笔记网站读取用户在账号中心的昵称和头像。“用微信登录”这类功能就是基于 OAuth 2.0 实现的,最常用的是授权码模式:
|
||||
|
||||
<div align="center"> <img src="pics/oauth-code-flow.png" width="760px"/> </div><br>
|
||||
|
||||
在本机用 Python 实现了一个最小的授权服务器,按上图运行了一遍,第 ① 步之后浏览器访问的地址和第 ⑥ 步笔记网站后端发送的请求如下(域名已替换,省略了部分字段):
|
||||
|
||||
```text
|
||||
GET https://id.example.com/authorize?response_type=code&client_id=notes-app
|
||||
&redirect_uri=https://notes.example.com/callback&scope=profile&state=x7Kp2
|
||||
&code_challenge=RQgc0f_GtuKCUitkJiCz7wNdN-_2JLHQ0JGLD9XxGtg&code_challenge_method=S256
|
||||
|
||||
POST https://id.example.com/token
|
||||
grant_type=authorization_code&code=R9YdiYheE6HIfYaA0e8LkQ
|
||||
&redirect_uri=https://notes.example.com/callback&client_id=notes-app
|
||||
&code_verifier=notes-demo-verifier-0123456789abcdefghijklmnop
|
||||
|
||||
{"access_token": "v-7DlxOYaDNY-ewb8cCXCujdIyR7qdtl", "token_type": "Bearer", "expires_in": 3600}
|
||||
```
|
||||
|
||||
几个参数的作用:
|
||||
|
||||
- code:授权码,经过浏览器传给笔记网站,规范建议最长 10 分钟有效,并且只能使用一次。同一个授权码第二次换令牌时,返回 400 {"error": "invalid_grant"};
|
||||
- code_verifier 和 code_challenge(PKCE):笔记网站先生成一个随机串 code_verifier,把它的 SHA-256 摘要 code_challenge 放在第一步的地址中,换令牌时再提交原文,授权服务器核对两者是否对应。攻击者即使截获了授权码,没有 code_verifier 也换不到令牌,实测同样返回 invalid_grant;
|
||||
- state:笔记网站生成的随机值,回调时检查是否与发出的一致,防止攻击者用自己账号的授权码构造回调地址,让用户登录到攻击者的账号上,这是一种 [CSRF](攻击技术.md#二跨站请求伪造);
|
||||
- access_token:访问令牌,由笔记网站的后端直接向授权服务器换取,不经过浏览器。
|
||||
|
||||
早期还有一种隐式模式,授权服务器直接把访问令牌放在重定向的地址中返回,令牌会出现在浏览器历史记录和日志中。RFC 9700(OAuth 2.0 安全最佳实践)规定不应该再使用隐式模式,没有能力保存密钥的客户端(例如单页应用、手机 App)必须使用 PKCE。
|
||||
|
||||
OAuth 2.0 本身只负责授权,访问令牌表示“可以读取昵称”,并不说明当前用户是谁。OpenID Connect 在它的基础上增加了 ID Token,这是一个包含用户 ID 的 JWT,专门用于登录,很多“第三方账号登录”使用的就是它。
|
||||
|
||||
扫码登录也是类似的思路,把手机上已有的登录状态安全地交给电脑:
|
||||
|
||||
1. 电脑网页向服务器申请一个二维码 ID,状态为“等待扫码”,并开始轮询这个 ID 的状态;
|
||||
2. 已登录的手机 App 扫码后,带着手机自己的令牌把二维码 ID 发给服务器,状态变为“已扫码”,电脑上显示“请在手机上确认”;
|
||||
3. 用户在手机上点击确认,服务器为电脑签发一个新的令牌,状态变为“已确认”,电脑轮询拿到令牌后完成登录。
|
||||
|
||||
需要注意的是,电脑拿到的是新签发的令牌,而不是手机的令牌;二维码 ID 有效期很短,确认这一步要求用户在手机上手动点击,防止别人把二维码发给用户诱导扫码。
|
||||
|
||||
### 缓存
|
||||
|
||||
#### 1. 优点
|
||||
@@ -604,6 +669,23 @@ Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
|
||||
If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT
|
||||
```
|
||||
|
||||
#### 5. 强缓存与协商缓存
|
||||
|
||||
浏览器使用缓存分为两种情况:
|
||||
|
||||
- 强缓存:缓存还在 max-age 规定的有效期内,直接使用,不发送请求;
|
||||
- 协商缓存:缓存已经过期,或者响应中有 no-cache,浏览器带上 If-None-Match 或 If-Modified-Since 向服务器确认,资源没有变化就返回 304,只传输首部,浏览器继续使用本地的缓存。
|
||||
|
||||
在本机用 Python 写一个服务器,a.js 返回 Cache-Control: max-age=600,b.js 返回 Cache-Control: no-cache,两者都带 ETag,用 Edge 打开同一个页面两次,服务器收到的请求如下:
|
||||
|
||||
```text
|
||||
第 1 次 /a.js 无条件请求 -> 200
|
||||
/b.js 无条件请求 -> 200
|
||||
第 2 次 /b.js If-None-Match: "b-v1" -> 304
|
||||
```
|
||||
|
||||
第 2 次打开时 a.js 没有发出请求,直接使用了强缓存;b.js 每次都要确认,但内容没有变化时只返回 304。常见的做法是 HTML 使用 no-cache,保证总能拿到最新的页面;JS、CSS 的文件名中带上内容的哈希值,例如 app.3f2a1c.js,设置很长的 max-age,内容变化时文件名随之改变,旧的缓存自然不再被使用。
|
||||
|
||||
### 内容协商
|
||||
|
||||
通过内容协商返回最合适的内容,例如根据浏览器的默认语言选择返回中文界面还是英文界面。
|
||||
@@ -638,9 +720,9 @@ Vary: Accept-Language
|
||||
|
||||
内容编码将实体主体进行压缩,从而减少传输的数据量。
|
||||
|
||||
常用的内容编码有:gzip、compress、deflate、identity。
|
||||
常用的内容编码有 gzip、deflate 和 br(Brotli),identity 表示不压缩。本机的 Edge 156 发出的请求中带的是 Accept-Encoding: gzip, deflate, br, zstd,较新的浏览器还支持 zstd。
|
||||
|
||||
浏览器发送 Accept-Encoding 首部,其中包含有它所支持的压缩算法,以及各自的优先级。服务器则从中选择一种,使用该算法对响应的消息主体进行压缩,并且发送 Content-Encoding 首部来告知浏览器它选择了哪一种算法。由于该内容协商过程是基于编码类型来选择资源的展现形式的,响应报文的 Vary 首部字段至少要包含 Content-Encoding。
|
||||
浏览器发送 Accept-Encoding 首部,其中包含有它所支持的压缩算法,以及各自的优先级。服务器则从中选择一种,使用该算法对响应的消息主体进行压缩,并且发送 Content-Encoding 首部来告知浏览器它选择了哪一种算法。由于响应的内容取决于请求中的 Accept-Encoding,响应报文的 Vary 首部字段要包含 Accept-Encoding,否则缓存服务器可能把压缩过的内容返回给不支持该算法的客户端。
|
||||
|
||||
### 范围请求
|
||||
|
||||
@@ -682,7 +764,7 @@ Accept-Ranges: bytes
|
||||
|
||||
### 分块传输编码
|
||||
|
||||
Chunked Transfer Encoding,可以把数据分割成多块,让浏览器逐步显示页面。
|
||||
Chunked Transfer Encoding,可以把数据分割成多块,让浏览器逐步显示页面。响应中带有 Transfer-Encoding: chunked 首部,不需要 Content-Length,每一块先写明长度,再写内容,最后以长度为 0 的块结束,适合事先不知道总长度的场景,例如边生成边返回的页面。HTTP/2 有自己的分帧机制,不再使用分块传输编码。
|
||||
|
||||
### 多部分对象集合
|
||||
|
||||
@@ -726,11 +808,9 @@ HTTP/1.1 使用虚拟主机技术,使得一台服务器拥有多个域名,
|
||||
|
||||
- 用户察觉得到正向代理的存在。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a314bb79-5b18-4e63-a976-3448bffa6f1b.png" width=""/> </div><br>
|
||||
|
||||
- 而反向代理一般位于内部网络中,用户察觉不到。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2d09a847-b854-439c-9198-b29c65810944.png" width=""/> </div><br>
|
||||
<div align="center"> <img src="pics/http-proxy.png" width="760px"/> </div><br>
|
||||
|
||||
#### 2. 网关
|
||||
|
||||
@@ -740,6 +820,68 @@ HTTP/1.1 使用虚拟主机技术,使得一台服务器拥有多个域名,
|
||||
|
||||
使用 SSL 等加密手段,在客户端和服务器之间建立一条安全的通信线路。
|
||||
|
||||
### WebSocket
|
||||
|
||||
HTTP 是请求-响应模式,服务器不能主动给客户端发消息。聊天、实时通知这类场景以前只能轮询:短轮询定时发请求,大部分请求都是空的;长轮询让服务器挂起请求,直到有新消息再响应,但每条消息仍要一次新的请求。WebSocket 在一个 TCP 连接上提供全双工通信,建立连接后双方随时都可以发送消息。
|
||||
|
||||
WebSocket 连接由一次 HTTP 请求升级而来:
|
||||
|
||||
```text
|
||||
GET /chat HTTP/1.1
|
||||
Host: www.example.com
|
||||
Upgrade: websocket
|
||||
Connection: Upgrade
|
||||
Sec-WebSocket-Key: Y3Mtbm90ZXMtMjAyNi0xMA==
|
||||
Sec-WebSocket-Version: 13
|
||||
|
||||
HTTP/1.1 101 Switching Protocols
|
||||
Upgrade: websocket
|
||||
Connection: Upgrade
|
||||
Sec-WebSocket-Accept: N5dfgp7eKvv+Po1vS+eAAHg5F1I=
|
||||
```
|
||||
|
||||
Sec-WebSocket-Key 是客户端随机生成的 16 字节的 Base64 编码。服务器在它后面拼上协议规定的 GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11,计算 SHA-1 后再做 Base64 编码,作为 Sec-WebSocket-Accept 返回,证明自己确实支持 WebSocket,而不是把请求当作普通的 HTTP 请求处理。之后连接上传输的不再是 HTTP 报文,而是 WebSocket 帧,帧头最短只有 2 字节,不用像 HTTP 那样每次都携带首部。
|
||||
|
||||
需要注意的是,长时间没有数据时,中间的代理或 NAT 可能会断开空闲的连接,所以通常定时发送 Ping 帧,对方回复 Pong 帧,以此保活并发现已经断开的连接。
|
||||
|
||||
SSE(Server-Sent Events)是另一种服务器推送方式:它是一个普通的 HTTP 响应,服务器不断地往响应中写入文本事件,只能由服务器发给客户端,浏览器断开后会自动重连。只需要服务器单向推送时(例如大模型逐字输出),SSE 更简单;客户端和服务器都需要随时发消息时(例如聊天、协同编辑),使用 WebSocket。
|
||||
|
||||
### 跨域
|
||||
|
||||
同源指的是协议、域名和端口都相同。浏览器的同源策略限制网页中的脚本读取其它源的响应,例如 https://shop.example.com 页面中的脚本请求 https://api.example.com/orders,请求能够发出去,但浏览器默认不把响应交给脚本。
|
||||
|
||||
跨域资源共享(Cross-Origin Resource Sharing, CORS)指的是服务器通过响应首部声明允许哪些源读取响应:
|
||||
|
||||
```text
|
||||
GET /orders HTTP/1.1
|
||||
Host: api.example.com
|
||||
Origin: https://shop.example.com
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Access-Control-Allow-Origin: https://shop.example.com
|
||||
```
|
||||
|
||||
GET、HEAD 和表单形式的 POST 这类简单请求直接发送;其它请求,例如 PUT 或者 Content-Type 为 application/json 的 POST,浏览器会先发一个 OPTIONS 预检请求,询问服务器是否允许,允许之后才发送真正的请求:
|
||||
|
||||
```text
|
||||
OPTIONS /orders/1024 HTTP/1.1
|
||||
Origin: https://shop.example.com
|
||||
Access-Control-Request-Method: PUT
|
||||
Access-Control-Request-Headers: content-type
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Access-Control-Allow-Origin: https://shop.example.com
|
||||
Access-Control-Allow-Methods: GET, PUT
|
||||
Access-Control-Allow-Headers: content-type
|
||||
Access-Control-Max-Age: 600
|
||||
```
|
||||
|
||||
Access-Control-Max-Age 表示预检结果可以缓存的秒数,期间相同的请求不再预检。跨域请求默认不携带 Cookie,前端设置 credentials: 'include' 后,服务器还要返回 Access-Control-Allow-Credentials: true,并且 Access-Control-Allow-Origin 不能是 *,必须写明具体的源。
|
||||
|
||||
在本机用两个端口模拟两个源,用 Edge 验证:服务器不返回 Access-Control-Allow-Origin 时,fetch 失败,但服务器的日志显示请求已经执行了;预检请求没有允许 PUT 时,浏览器不再发送 PUT;携带 Cookie 而服务器返回 * 时,fetch 同样失败。
|
||||
|
||||
需要注意的是,CORS 只决定浏览器是否把响应交给脚本,并不是安全措施:服务器仍然执行了请求,curl 这类不经过浏览器的工具也完全不受限制,权限要靠认证和 [CSRF 防护](攻击技术.md#二跨站请求伪造) 保证。另一种解决跨域的办法是同源的反向代理,例如由 Nginx 把 https://shop.example.com/api 转发给后端,浏览器看到的就是同源的请求。
|
||||
|
||||
## 六、HTTPS
|
||||
|
||||
HTTP 有以下安全性问题:
|
||||
@@ -754,7 +896,7 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSL(Secure Sockets Layer)
|
||||
|
||||
通过使用 SSL,HTTPS 具有了加密(防窃听)、认证(防伪装)和完整性保护(防篡改)。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/ssl-offloading.jpg" width="700"/> </div><br>
|
||||
<div align="center"> <img src="pics/https-layers.png" width="720px"/> </div><br>
|
||||
|
||||
### 加密
|
||||
|
||||
@@ -765,7 +907,7 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSL(Secure Sockets Layer)
|
||||
- 优点:运算速度快;
|
||||
- 缺点:无法安全地将密钥传输给通信方。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/7fffa4b8-b36d-471f-ad0c-a88ee763bb76.png" width="600"/> </div><br>
|
||||
<div align="center"> <img src="pics/crypto-symmetric.png" width="720px"/> </div><br>
|
||||
|
||||
#### 2.非对称密钥加密
|
||||
|
||||
@@ -773,23 +915,23 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSL(Secure Sockets Layer)
|
||||
|
||||
公开密钥所有人都可以获得,通信发送方获得接收方的公开密钥之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密。
|
||||
|
||||
非对称密钥除了用来加密,还可以用来进行签名。因为私有密钥无法被其他人获取,因此通信发送方使用其私有密钥进行签名,通信接收方使用发送方的公开密钥对签名进行解密,就能判断这个签名是否正确。
|
||||
非对称密钥除了用来加密,还可以用来进行签名。因为私有密钥无法被其他人获取,因此通信发送方使用其私有密钥进行签名,通信接收方使用发送方的公开密钥对签名进行验证,就能判断这个签名是否正确。
|
||||
|
||||
- 优点:可以更安全地将公开密钥传输给通信发送方;
|
||||
- 缺点:运算速度慢。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/39ccb299-ee99-4dd1-b8b4-2f9ec9495cb4.png" width="600"/> </div><br>
|
||||
<div align="center"> <img src="pics/crypto-asymmetric.png" width="720px"/> </div><br>
|
||||
|
||||
#### 3. HTTPS 采用的加密方式
|
||||
|
||||
上面提到对称密钥加密方式的传输效率更高,但是无法安全地将密钥 Secret Key 传输给通信方。而非对称密钥加密方式可以保证传输的安全性,因此我们可以利用非对称密钥加密方式将 Secret Key 传输给通信方。HTTPS 采用混合的加密机制,正是利用了上面提到的方案:
|
||||
上面提到对称密钥加密方式的传输效率更高,但是无法安全地将密钥 Secret Key 传输给通信方。而非对称密钥加密方式可以保证传输的安全性,因此可以利用非对称密钥加密方式将 Secret Key 传输给通信方。HTTPS 采用混合的加密机制,正是利用了上面提到的方案:
|
||||
|
||||
- 使用非对称密钥加密方式,传输对称密钥加密方式所需要的 Secret Key,从而保证安全性;
|
||||
- 获取到 Secret Key 后,再使用对称密钥加密方式进行通信,从而保证效率。(下图中的 Session Key 就是 Secret Key)
|
||||
- 获取到 Secret Key 后,再使用对称密钥加密方式进行通信,从而保证效率。(下图中的会话密钥就是 Secret Key)
|
||||
|
||||
需要注意的是,TLS 1.3 不再用公钥加密传输对称密钥,而是通过 ECDHE 密钥交换协商出会话密钥,非对称密钥只用于签名认证。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/How-HTTPS-Works.png" width="600"/> </div><br>
|
||||
<div align="center"> <img src="pics/https-hybrid.png" width="740px"/> </div><br>
|
||||
|
||||
### 认证
|
||||
|
||||
@@ -801,7 +943,17 @@ HTTPS 并不是新协议,而是让 HTTP 先和 SSL(Secure Sockets Layer)
|
||||
|
||||
进行 HTTPS 通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证,如果验证通过,就可以开始通信了。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2017-06-11-ca.png" width=""/> </div><br>
|
||||
<div align="center"> <img src="pics/cert-chain.png" width="760px"/> </div><br>
|
||||
|
||||
### TLS 握手
|
||||
|
||||
TLS 握手完成三件事:协商加密算法、验证服务器的证书、协商出会话密钥。目前常用的密钥交换方式是 ECDHE:双方各自临时生成一对椭圆曲线密钥,把公钥发给对方,再用自己的私钥和对方的公钥算出相同的共享密钥。会话密钥本身从不在网络上传输,即使服务器的证书私钥日后泄露,之前录下的通信也无法解密,称为前向安全。服务器还要用证书的私钥对握手内容签名,证明自己就是证书的持有者。
|
||||
|
||||
下图是本机用 openssl s_client 连接两个网站时记录的握手报文:
|
||||
|
||||
<div align="center"> <img src="pics/tls-handshake.png" width="760px"/> </div><br>
|
||||
|
||||
TLS 1.2 要 2 个 RTT 之后才能发送 HTTP 请求。TLS 1.3 把 ECDHE 公钥直接放在 ClientHello 中,服务器回复 ServerHello 时双方就能算出密钥,之后的握手报文(图中花括号内)都已加密,1 个 RTT 后就能发送请求;TLS 1.3 还去掉了 RSA 密钥交换等不安全的算法。
|
||||
|
||||
### 完整性保护
|
||||
|
||||
@@ -809,7 +961,7 @@ SSL 提供报文摘要功能来进行完整性保护。
|
||||
|
||||
HTTP 也提供了 MD5 报文摘要功能,但不是安全的。例如报文内容被篡改之后,同时重新计算 MD5 的值,通信接收方是无法意识到发生了篡改。
|
||||
|
||||
HTTPS 的报文摘要功能之所以安全,是因为它结合了加密和认证这两个操作。试想一下,加密之后的报文,遭到篡改之后,也很难重新计算报文摘要,因为无法轻易获取明文。
|
||||
HTTPS 的报文摘要功能之所以安全,是因为计算摘要时用到了握手协商出的会话密钥(HMAC,或者 AES-GCM 等算法自带的认证标签)。攻击者没有这个密钥,篡改报文之后无法算出正确的摘要,接收方校验失败就会断开连接。
|
||||
|
||||
### HTTPS 的缺点
|
||||
|
||||
@@ -830,7 +982,7 @@ HTTP/1.x 实现简单是以牺牲性能为代价的:
|
||||
|
||||
HTTP/2.0 将报文分成 HEADERS 帧和 DATA 帧,它们都是二进制格式的。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/86e6a91d-a285-447a-9345-c5484b8d0c47.png" width="400"/> </div><br>
|
||||
<div align="center"> <img src="pics/h2-frames.png" width="760px"/> </div><br>
|
||||
|
||||
在通信过程中,只会有一个 TCP 连接存在,它承载了任意数量的双向数据流(Stream)。
|
||||
|
||||
@@ -838,13 +990,13 @@ HTTP/2.0 将报文分成 HEADERS 帧和 DATA 帧,它们都是二进制格式
|
||||
- 消息(Message)是与逻辑请求或响应对应的完整的一系列帧。
|
||||
- 帧(Frame)是最小的通信单位,来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/af198da1-2480-4043-b07f-a3b91a88b815.png" width="600"/> </div><br>
|
||||
<div align="center"> <img src="pics/h2-streams.png" width="760px"/> </div><br>
|
||||
|
||||
### 服务端推送
|
||||
|
||||
HTTP/2.0 在客户端请求一个资源时,会把相关的资源一起发送给客户端,客户端就不需要再次发起请求了。例如客户端请求 page.html 页面,服务端就把 script.js 和 style.css 等与之相关的资源一起发给客户端。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/e3f1657c-80fc-4dfa-9643-bf51abd201c6.png" width="800"/> </div><br>
|
||||
<div align="center"> <img src="pics/h2-push.png" width="720px"/> </div><br>
|
||||
|
||||
需要注意的是,Chrome 106 起默认禁用了服务端推送,其它基于 Chromium 的浏览器也随之跟进。
|
||||
|
||||
@@ -856,7 +1008,19 @@ HTTP/2.0 要求客户端和服务器同时维护和更新一个包含之前见
|
||||
|
||||
不仅如此,HTTP/2.0 也使用 Huffman 编码对首部字段进行压缩。
|
||||
|
||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/_u4E0B_u8F7D.png" width="600"/> </div><br>
|
||||
<div align="center"> <img src="pics/hpack.png" width="760px"/> </div><br>
|
||||
|
||||
### HTTP/3
|
||||
|
||||
HTTP/2 在一个 TCP 连接上复用多个流,但 TCP 只保证整个字节流按序到达:一个报文段丢失时,后面已经到达的数据也要等它重传,所有的流都被阻塞,称为队头阻塞。
|
||||
|
||||
HTTP/3 改为基于 UDP 的 QUIC 协议:
|
||||
|
||||
- 每个流单独保证顺序,一个流丢包不影响其它流;
|
||||
- QUIC 内置了 TLS 1.3,传输层握手和加密握手合并,新连接 1 个 RTT 后就能发送请求,恢复之前的会话时可以 0 RTT;
|
||||
- 连接用连接 ID 标识,而不是 IP 地址和端口,手机从 Wi-Fi 切换到移动网络时连接不用重建。
|
||||
|
||||
浏览器通常先用 HTTP/2 访问,从响应首部 Alt-Svc 得知服务器支持 HTTP/3 后再切换,例如 www.example.com 的响应中有 alt-svc: h3=":443"; ma=86400。
|
||||
|
||||
## 八、HTTP/1.1 新特性
|
||||
|
||||
@@ -889,6 +1053,8 @@ GET /test/demo_form.asp?name1=value1&name2=value2 HTTP/1.1
|
||||
```http
|
||||
POST /test/demo_form.asp HTTP/1.1
|
||||
Host: w3schools.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
name1=value1&name2=value2
|
||||
```
|
||||
|
||||
@@ -922,7 +1088,7 @@ GET /pageX HTTP/1.1
|
||||
POST /add_row HTTP/1.1 不是幂等的,如果调用多次,就会增加多行记录:
|
||||
|
||||
```text
|
||||
POST /add_row HTTP/1.1 -> Adds a 1nd row
|
||||
POST /add_row HTTP/1.1 -> Adds a 1st row
|
||||
POST /add_row HTTP/1.1 -> Adds a 2nd row
|
||||
POST /add_row HTTP/1.1 -> Adds a 3rd row
|
||||
```
|
||||
@@ -945,42 +1111,46 @@ DELETE /idX/delete HTTP/1.1 -> Returns 404
|
||||
|
||||
### XMLHttpRequest
|
||||
|
||||
为了阐述 POST 和 GET 的另一个区别,需要先了解 XMLHttpRequest:
|
||||
XMLHttpRequest 是浏览器提供的 API,用于在不刷新页面的情况下向服务器发送请求,是 AJAX 的基础,现在更常用的是 fetch()。
|
||||
|
||||
> XMLHttpRequest 是一个 API,它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。这使得网页只更新一部分页面而不会打扰到用户。XMLHttpRequest 在 AJAX 中被大量使用。
|
||||
|
||||
- 在使用 XMLHttpRequest 的 POST 方法时,浏览器会先发送 Header 再发送 Data。但并不是所有浏览器会这么做,例如火狐就不会。
|
||||
- 而 GET 方法 Header 和 Data 会一起发送。
|
||||
网上流传一种说法:XMLHttpRequest 发送 POST 时,会先发送首部,再单独发送请求体,GET 则一次发完。HTTP 规范中没有这样的规定,这只是个别浏览器早期的实现细节,不能作为 GET 和 POST 的区别。在本机用 Edge 记录网络日志(--log-net-log),通过 XMLHttpRequest 发送一个带 21 字节请求体的 POST 请求,首部和请求体是在同一次 socket 写入中发出的,共 723 字节。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [RFC 7519: JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519)
|
||||
- [RFC 6749: The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749)
|
||||
- [RFC 7636: Proof Key for Code Exchange (PKCE)](https://www.rfc-editor.org/rfc/rfc7636)
|
||||
- [RFC 9700: Best Current Practice for OAuth 2.0 Security](https://www.rfc-editor.org/rfc/rfc9700)
|
||||
- [OWASP: JSON Web Token Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_Cheat_Sheet.html)
|
||||
- [OWASP: HTML5 Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html)
|
||||
- 上野宣. 图解 HTTP[M]. 人民邮电出版社, 2014.
|
||||
- [MDN : HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP)
|
||||
- [MDN : Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
|
||||
- [HTTP/2 简介](https://developers.google.com/web/fundamentals/performance/http2/?hl=zh-cn)
|
||||
- [htmlspecialchars](http://php.net/manual/zh/function.htmlspecialchars.php)
|
||||
- [Difference between file URI and URL in java](http://java2db.com/java-io/how-to-get-and-the-difference-between-file-uri-and-url-in-java)
|
||||
- [Difference between file URI and URL in java](https://web.archive.org/web/20191216080403/http://java2db.com:80/java-io/how-to-get-and-the-difference-between-file-uri-and-url-in-java)
|
||||
- [How to Fix SQL Injection Using Java PreparedStatement & CallableStatement](https://software-security.sans.org/developer-how-to/fix-sql-injection-in-java-using-prepared-callable-statement)
|
||||
- [浅谈 HTTP 中 Get 与 Post 的区别](https://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html)
|
||||
- [Are http:// and www really necessary?](https://www.webdancers.com/are-http-and-www-necesary/)
|
||||
- [HTTP (HyperText Transfer Protocol)](https://www.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html)
|
||||
- [HTTP (HyperText Transfer Protocol)](https://www3.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html)
|
||||
- [Web-VPN: Secure Proxies with SPDY & Chrome](https://www.igvita.com/2011/12/01/web-vpn-secure-proxies-with-spdy-chrome/)
|
||||
- [File:HTTP persistent connection.svg](http://en.wikipedia.org/wiki/File:HTTP_persistent_connection.svg)
|
||||
- [Proxy server](https://en.wikipedia.org/wiki/Proxy_server)
|
||||
- [What Is This HTTPS/SSL Thing And Why Should You Care?](https://www.x-cart.com/blog/what-is-https-and-ssl.html)
|
||||
- [What is SSL Offloading?](https://securebox.comodo.com/ssl-sniffing/ssl-offloading/)
|
||||
- [Sun Directory Server Enterprise Edition 7.0 Reference - Key Encryption](https://docs.oracle.com/cd/E19424-01/820-4811/6ng8i26bn/index.html)
|
||||
- [An Introduction to Mutual SSL Authentication](https://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication)
|
||||
- [The Difference Between URLs and URIs](https://danielmiessler.com/study/url-uri/)
|
||||
- [Cookie 与 Session 的区别](https://juejin.im/entry/5766c29d6be3ff006a31b84e#comment)
|
||||
- [COOKIE 和 SESSION 有什么区别](https://www.zhihu.com/question/19786827)
|
||||
- [Cookie/Session 的机制与安全](https://harttle.land/2015/08/10/cookie-session.html)
|
||||
- [HTTPS 证书原理](https://shijianan.com/2017/06/11/https/)
|
||||
- [What is the difference between a URI, a URL and a URN?](https://stackoverflow.com/questions/176264/what-is-the-difference-between-a-uri-a-url-and-a-urn)
|
||||
- [XMLHttpRequest](https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest)
|
||||
- [XMLHttpRequest (XHR) Uses Multiple Packets for HTTP POST?](https://blog.josephscott.org/2009/08/27/xmlhttprequest-xhr-uses-multiple-packets-for-http-post/)
|
||||
- [Symmetric vs. Asymmetric Encryption – What are differences?](https://www.ssl2buy.com/wiki/symmetric-vs-asymmetric-encryption-what-are-differences)
|
||||
- [Web 性能优化与 HTTP/2](https://www.kancloud.cn/digest/web-performance-http2)
|
||||
- [HTTP/2 简介](https://developers.google.com/web/fundamentals/performance/http2/?hl=zh-cn)
|
||||
- [RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3](https://www.rfc-editor.org/rfc/rfc8446)
|
||||
- [RFC 7541: HPACK: Header Compression for HTTP/2](https://www.rfc-editor.org/rfc/rfc7541)
|
||||
- [RFC 9114: HTTP/3](https://www.rfc-editor.org/rfc/rfc9114)
|
||||
- [RFC 9000: QUIC](https://www.rfc-editor.org/rfc/rfc9000)
|
||||
- [RFC 6455: The WebSocket Protocol](https://www.rfc-editor.org/rfc/rfc6455)
|
||||
|
||||
|
After Width: | Height: | Size: 169 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 184 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 120 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 234 KiB |
|
After Width: | Height: | Size: 179 KiB |
@@ -0,0 +1,58 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="760" height="300" viewBox="0 0 760 300">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="380" y="28" class="title">证书链:www.baidu.com 的证书如何被信任</text>
|
||||
<rect x="30" y="60" width="220" height="110" rx="6" fill="#C6E4FB" stroke="#7FB2D6"/>
|
||||
<text x="140" y="82" class="c sub b" style="fill:#444">服务器证书</text>
|
||||
<text x="140" y="104" class="c sub mono" style="fill:#444">baidu.com</text>
|
||||
<text x="140" y="130" class="c sub">公钥:RSA 2048 位</text>
|
||||
<text x="140" y="148" class="c sub">有效期 2026-07-09 ~ 2027-01-24</text>
|
||||
<line x1="278" y1="115" x2="254" y2="115" class="arrow "/>
|
||||
<text x="266" y="196" class="c sub"></text>
|
||||
<rect x="280" y="60" width="220" height="110" rx="6" fill="#EAE9E7" stroke="#BFBEBA"/>
|
||||
<text x="390" y="82" class="c sub b" style="fill:#444">中间证书</text>
|
||||
<text x="390" y="104" class="c sub mono" style="fill:#444">GlobalSign RSA OV SSL CA 2018</text>
|
||||
<text x="390" y="130" class="c sub">由根证书签名</text>
|
||||
<text x="390" y="148" class="c sub">随服务器证书一起发送</text>
|
||||
<line x1="528" y1="115" x2="504" y2="115" class="arrow "/>
|
||||
<text x="516" y="196" class="c sub"></text>
|
||||
<rect x="530" y="60" width="220" height="110" rx="6" fill="#C6ECE9" stroke="#7DBCB7"/>
|
||||
<text x="640" y="82" class="c sub b" style="fill:#444">根证书</text>
|
||||
<text x="640" y="104" class="c sub mono" style="fill:#444">GlobalSign Root R3</text>
|
||||
<text x="640" y="130" class="c sub">自签名</text>
|
||||
<text x="640" y="148" class="c sub">预装在操作系统的信任列表中</text>
|
||||
<text x="255" y="196" class="c sub" style="fill:#766AA8">用中间证书的公钥验证服务器证书的签名</text>
|
||||
<text x="505" y="196" class="c sub" style="fill:#766AA8">用根证书的公钥验证中间证书</text>
|
||||
<text x="30" y="236" class="sub">浏览器还要检查:访问的域名 www.baidu.com 与证书中的域名匹配(Subject Alternative Name 中有 *.baidu.com),</text>
|
||||
<text x="30" y="254" class="sub">证书在有效期内且没有被吊销。任何一步失败都会提示“连接不是私密连接”。</text>
|
||||
<text x="30" y="278" class="sub">证书和签名是公开的,伪造者拿不到 CA 的私钥,就无法为自己的公钥生成有效签名。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,59 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="250" viewBox="0 0 720 250">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="360" y="28" class="title">非对称加密:公钥加密、私钥解密;私钥签名、公钥验证</text>
|
||||
<text x="30" y="66" class="b">加密</text>
|
||||
<rect x="90" y="50" width="110" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="145" y="69" class="c sub" style="fill:#444">会话密钥</text>
|
||||
<line x1="202" y1="65" x2="286" y2="65" class="arrow "/>
|
||||
<text x="244" y="57" class="c sub" style="fill:#207773">服务器公钥</text>
|
||||
<rect x="290" y="50" width="150" height="30" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="365" y="69" class="c sub" style="fill:#444">密文 256 字节</text>
|
||||
<line x1="442" y1="65" x2="526" y2="65" class="arrow "/>
|
||||
<text x="484" y="57" class="c sub" style="fill:#766AA8">服务器私钥</text>
|
||||
<rect x="530" y="50" width="110" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="585" y="69" class="c sub" style="fill:#444">会话密钥</text>
|
||||
<text x="90" y="100" class="sub">任何人都能用公钥加密,只有持有私钥的服务器能解开</text>
|
||||
<text x="30" y="156" class="b">签名</text>
|
||||
<rect x="90" y="140" width="110" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="145" y="159" class="c sub" style="fill:#444">证书内容</text>
|
||||
<line x1="202" y1="155" x2="286" y2="155" class="arrow "/>
|
||||
<text x="244" y="147" class="c sub" style="fill:#766AA8">CA 私钥签名</text>
|
||||
<rect x="290" y="140" width="150" height="30" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="365" y="159" class="c sub" style="fill:#444">签名</text>
|
||||
<line x1="442" y1="155" x2="526" y2="155" class="arrow "/>
|
||||
<text x="484" y="147" class="c sub" style="fill:#207773">CA 公钥验证</text>
|
||||
<rect x="530" y="140" width="110" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="585" y="159" class="c sub" style="fill:#444">签名有效</text>
|
||||
<text x="90" y="190" class="sub">只有 CA 能生成签名,任何人都能用 CA 的公钥检查,内容改动一个字节签名就对不上</text>
|
||||
<text x="30" y="236" class="sub">2048 位 RSA 的密文和签名都是 256 字节。非对称运算比对称加密慢得多,所以只用在握手阶段。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,50 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="200" viewBox="0 0 720 200">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="360" y="28" class="title">对称加密:加密和解密用同一个密钥</text>
|
||||
<rect x="30" y="80" width="120" height="36" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="90" y="102" class="c sub" style="fill:#444">转账 100 元</text>
|
||||
<line x1="152" y1="98" x2="222" y2="98" class="arrow "/>
|
||||
<text x="187" y="90" class="c sub">AES 加密</text>
|
||||
<rect x="226" y="80" width="270" height="36" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="361" y="102" class="c sub mono" style="fill:#444">c0b9bea2112248bbc17e8d6a15e542de</text>
|
||||
<line x1="498" y1="98" x2="568" y2="98" class="arrow "/>
|
||||
<text x="533" y="90" class="c sub">AES 解密</text>
|
||||
<rect x="572" y="80" width="120" height="36" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="632" y="102" class="c sub" style="fill:#444">转账 100 元</text>
|
||||
<path d="M182,128 v-4 a5,5 0 0 1 10,0 v4" fill="none" stroke="#B8B0DE" stroke-width="1.8"/>
|
||||
<rect x="179" y="128" width="16" height="12" rx="2" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1.2"/>
|
||||
<path d="M528,128 v-4 a5,5 0 0 1 10,0 v4" fill="none" stroke="#B8B0DE" stroke-width="1.8"/>
|
||||
<rect x="525" y="128" width="16" height="12" rx="2" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1.2"/>
|
||||
<text x="360" y="150" class="c sub mono" style="fill:#766AA8">同一个密钥 K = 000102…0e0f(16 字节)</text>
|
||||
<text x="30" y="186" class="sub">用 openssl 实际计算(AES-128-CBC):14 字节的明文补齐到 16 字节;没有 K 无法还原,但 K 本身怎样安全地交给对方是个问题。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,72 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="760" height="300" viewBox="0 0 760 300">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="380" y="28" class="title">HTTP/2 的二进制分帧:一次 GET 请求和响应</text>
|
||||
<rect x="30" y="52" width="300" height="96" rx="5" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1.2"/>
|
||||
<line x1="30" y1="66" x2="330" y2="66" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<circle cx="39" cy="59" r="2.2" fill="#BBBBBB"/>
|
||||
<circle cx="47" cy="59" r="2.2" fill="#BBBBBB"/>
|
||||
<circle cx="55" cy="59" r="2.2" fill="#BBBBBB"/>
|
||||
<text x="39" y="82" class="sub mono">GET /index.html HTTP/1.1</text>
|
||||
<text x="39" y="98" class="sub mono">Host: www.example.com</text>
|
||||
<text x="39" y="114" class="sub mono">User-Agent: Mozilla/5.0 …</text>
|
||||
<text x="39" y="130" class="sub mono">Accept: text/html</text>
|
||||
<text x="180" y="168" class="c sub">HTTP/1.1:文本,150 字节</text>
|
||||
<line x1="340" y1="100" x2="400" y2="100" class="arrow "/>
|
||||
<text x="370" y="92" class="c sub">HTTP/2</text>
|
||||
<rect x="400" y="60" width="70" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="435" y="79" class="c sub b" style="fill:#444">HEADERS</text>
|
||||
<rect x="470" y="60" width="80" height="30" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="510" y="79" class="c sub mono" style="fill:#444">stream 1</text>
|
||||
<rect x="550" y="60" width="120" height="30" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="610" y="79" class="c sub" style="fill:#444">78 字节</text>
|
||||
<text x="680" y="80" class="sub">请求首部</text>
|
||||
<rect x="400" y="130" width="70" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="435" y="149" class="c sub b" style="fill:#444">HEADERS</text>
|
||||
<rect x="470" y="130" width="80" height="30" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="510" y="149" class="c sub mono" style="fill:#444">stream 1</text>
|
||||
<rect x="550" y="130" width="120" height="30" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="610" y="149" class="c sub" style="fill:#444">… 字节</text>
|
||||
<text x="680" y="150" class="sub">响应首部</text>
|
||||
<rect x="400" y="170" width="70" height="30" rx="3" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1"/>
|
||||
<text x="435" y="189" class="c sub b" style="fill:#444">DATA</text>
|
||||
<rect x="470" y="170" width="80" height="30" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="510" y="189" class="c sub mono" style="fill:#444">stream 1</text>
|
||||
<rect x="550" y="170" width="120" height="30" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="610" y="189" class="c sub" style="fill:#444">577 字节</text>
|
||||
<text x="680" y="190" class="sub">页面内容</text>
|
||||
<text x="410" y="52" class="sub"></text>
|
||||
<text x="400" y="122" class="sub b" style="fill:#444">服务器返回:</text>
|
||||
<text x="30" y="230" class="sub">每个帧前面有 9 字节的帧头:长度、类型、标志和流 ID。请求和响应属于同一个流(stream 1),</text>
|
||||
<text x="30" y="248" class="sub">所以多个请求可以在一个 TCP 连接上交错发送,接收方按流 ID 重新组装。</text>
|
||||
<text x="30" y="274" class="sub">78 字节是用 hpack 库按图中首部实际编码的结果;577 字节是 www.example.com 首页的大小。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
@@ -0,0 +1,49 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="260" viewBox="0 0 720 260">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="360" y="28" class="title">服务端推送:请求页面时一起发送样式</text>
|
||||
<rect x="80" y="46" width="140" height="32" rx="6" fill="#C6ECE9" stroke="#7DBCB7"/>
|
||||
<text x="150" y="66.5" class="c sub b">浏览器</text>
|
||||
<line x1="150" y1="80" x2="150" y2="230" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<rect x="500" y="46" width="140" height="32" rx="6" fill="#C6E4FB" stroke="#7FB2D6"/>
|
||||
<text x="570" y="66.5" class="c sub b">服务器</text>
|
||||
<line x1="570" y1="80" x2="570" y2="230" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<line x1="150" y1="100" x2="570" y2="100" class="arrow "/>
|
||||
<text x="360" y="94" class="c sub mono" style="fill:#444">stream 1:GET /page.html</text>
|
||||
<line x1="570" y1="134" x2="150" y2="134" class="arrow dash"/>
|
||||
<text x="360" y="128" class="c sub mono" style="fill:#444">stream 1:PUSH_PROMISE /style.css</text>
|
||||
<line x1="570" y1="166" x2="150" y2="166" class="arrow dash"/>
|
||||
<text x="360" y="160" class="c sub mono" style="fill:#444">stream 1:page.html 的内容</text>
|
||||
<line x1="570" y1="198" x2="150" y2="198" class="arrow dash"/>
|
||||
<text x="360" y="192" class="c sub mono" style="fill:#444">stream 2:style.css 的内容</text>
|
||||
<text x="30" y="250" class="sub">服务器推送的流 ID 为偶数。浏览器解析到 style.css 时它已经在缓存里,省去一次请求的往返。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1,60 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="760" height="230" viewBox="0 0 760 230">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="380" y="28" class="title">多路复用:三个请求共用一个 TCP 连接</text>
|
||||
<rect x="40" y="70" width="680" height="64" rx="32" fill="#FFFFFF" stroke="#BBBBBB"/>
|
||||
<rect x="80" y="86" width="60" height="32" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="110" y="106" class="c sub" style="fill:#444">HEADERS 1</text>
|
||||
<rect x="150" y="86" width="60" height="32" rx="3" fill="#C6ECE9" stroke="#7DBCB7" stroke-width="1"/>
|
||||
<text x="180" y="106" class="c sub" style="fill:#444">HEADERS 3</text>
|
||||
<rect x="220" y="86" width="60" height="32" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="250" y="106" class="c sub" style="fill:#444">DATA 1</text>
|
||||
<rect x="290" y="86" width="60" height="32" rx="3" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1"/>
|
||||
<text x="320" y="106" class="c sub" style="fill:#444">HEADERS 5</text>
|
||||
<rect x="360" y="86" width="60" height="32" rx="3" fill="#C6ECE9" stroke="#7DBCB7" stroke-width="1"/>
|
||||
<text x="390" y="106" class="c sub" style="fill:#444">DATA 3</text>
|
||||
<rect x="430" y="86" width="60" height="32" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="460" y="106" class="c sub" style="fill:#444">DATA 1</text>
|
||||
<rect x="500" y="86" width="60" height="32" rx="3" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1"/>
|
||||
<text x="530" y="106" class="c sub" style="fill:#444">DATA 5</text>
|
||||
<rect x="570" y="86" width="60" height="32" rx="3" fill="#C6ECE9" stroke="#7DBCB7" stroke-width="1"/>
|
||||
<text x="600" y="106" class="c sub" style="fill:#444">DATA 3</text>
|
||||
<rect x="640" y="86" width="60" height="32" rx="3" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1"/>
|
||||
<text x="670" y="106" class="c sub" style="fill:#444">DATA 5</text>
|
||||
<line x1="700" y1="102" x2="728" y2="102" class="arrow "/>
|
||||
<text x="40" y="60" class="sub b" style="fill:#444">一个 TCP 连接</text>
|
||||
<text x="40" y="162" class="sub" style="fill:#296898">stream 1:/index.html</text>
|
||||
<text x="260" y="162" class="sub" style="fill:#207773">stream 3:/style.css</text>
|
||||
<text x="470" y="162" class="sub" style="fill:#766AA8">stream 5:/app.js</text>
|
||||
<text x="40" y="196" class="sub">帧可以交错发送,一个响应慢不会挡住其它响应;但 TCP 丢包时所有流都要等重传,这是 HTTP/3 改用 QUIC 的原因。</text>
|
||||
<text x="40" y="214" class="sub">客户端发起的流 ID 为奇数。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,93 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="760" height="330" viewBox="0 0 760 330">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="380" y="28" class="title">首部压缩:第二次请求只需 21 字节</text>
|
||||
<rect x="30" y="50" width="120" height="24" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="90" y="66" class="c sub" style="fill:#444">首部</text>
|
||||
<rect x="150" y="50" width="190" height="24" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="245" y="66" class="c sub" style="fill:#444">值</text>
|
||||
<rect x="340" y="50" width="300" height="24" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="490" y="66" class="c sub" style="fill:#444">编码方式</text>
|
||||
<rect x="640" y="50" width="80" height="24" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="680" y="66" class="c sub" style="fill:#444">字节数</text>
|
||||
<rect x="30" y="74" width="120" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="90" y="92" class="c sub mono" style="fill:#444">:method</text>
|
||||
<rect x="150" y="74" width="190" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="245" y="92" class="c sub mono" style="fill:#444">GET</text>
|
||||
<rect x="340" y="74" width="300" height="28" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="490" y="92" class="c sub" style="fill:#444">静态表第 2 项</text>
|
||||
<rect x="640" y="74" width="80" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="680" y="92" class="c sub mono" style="fill:#444">1</text>
|
||||
<rect x="30" y="102" width="120" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="90" y="120" class="c sub mono" style="fill:#444">:scheme</text>
|
||||
<rect x="150" y="102" width="190" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="245" y="120" class="c sub mono" style="fill:#444">https</text>
|
||||
<rect x="340" y="102" width="300" height="28" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="490" y="120" class="c sub" style="fill:#444">静态表第 7 项</text>
|
||||
<rect x="640" y="102" width="80" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="680" y="120" class="c sub mono" style="fill:#444">1</text>
|
||||
<rect x="30" y="130" width="120" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="90" y="148" class="c sub mono" style="fill:#444">:authority</text>
|
||||
<rect x="150" y="130" width="190" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="245" y="148" class="c sub mono" style="fill:#444">www.example.com</text>
|
||||
<rect x="340" y="130" width="300" height="28" rx="3" fill="#C6ECE9" stroke="#7DBCB7" stroke-width="1"/>
|
||||
<text x="490" y="148" class="c sub" style="fill:#444">动态表(第一次请求时加入)</text>
|
||||
<rect x="640" y="130" width="80" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="680" y="148" class="c sub mono" style="fill:#444">1</text>
|
||||
<rect x="30" y="158" width="120" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="90" y="176" class="c sub mono" style="fill:#444">:path</text>
|
||||
<rect x="150" y="158" width="190" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="245" y="176" class="c sub mono" style="fill:#444">/style.css</text>
|
||||
<rect x="340" y="158" width="300" height="28" rx="3" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1"/>
|
||||
<text x="490" y="176" class="c sub" style="fill:#444">新值:名字用静态表,值用 Huffman 编码</text>
|
||||
<rect x="640" y="158" width="80" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="680" y="176" class="c sub mono" style="fill:#444">9</text>
|
||||
<rect x="30" y="186" width="120" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="90" y="204" class="c sub mono" style="fill:#444">user-agent</text>
|
||||
<rect x="150" y="186" width="190" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="245" y="204" class="c sub" style="fill:#444">Mozilla/5.0 …(64 字节)</text>
|
||||
<rect x="340" y="186" width="300" height="28" rx="3" fill="#C6ECE9" stroke="#7DBCB7" stroke-width="1"/>
|
||||
<text x="490" y="204" class="c sub" style="fill:#444">动态表(第一次请求时加入)</text>
|
||||
<rect x="640" y="186" width="80" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="680" y="204" class="c sub mono" style="fill:#444">1</text>
|
||||
<rect x="30" y="214" width="120" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="90" y="232" class="c sub mono" style="fill:#444">accept</text>
|
||||
<rect x="150" y="214" width="190" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="245" y="232" class="c sub mono" style="fill:#444">text/css</text>
|
||||
<rect x="340" y="214" width="300" height="28" rx="3" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1"/>
|
||||
<text x="490" y="232" class="c sub" style="fill:#444">新值:名字用静态表,值用 Huffman 编码</text>
|
||||
<rect x="640" y="214" width="80" height="28" rx="3" fill="#FFFFFF" stroke="#BBBBBB" stroke-width="1"/>
|
||||
<text x="680" y="232" class="c sub mono" style="fill:#444">8</text>
|
||||
<text x="30" y="272" class="sub">同样的请求用 HTTP/1.1 的文本格式是 148 字节;第一次请求要建立动态表,编码后 78 字节。</text>
|
||||
<text x="30" y="290" class="sub">静态表是协议规定的 61 个常见首部;动态表由双方各自维护,保存本连接中出现过的首部,之后只发送序号。</text>
|
||||
<text x="30" y="314" class="sub">以上字节数由 hpack 4.0 库编码得到(RFC 7541)。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,52 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="740" height="300" viewBox="0 0 740 300">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="370" y="28" class="title">CONNECT:通过代理建立隧道</text>
|
||||
<rect x="50" y="46" width="140" height="32" rx="6" fill="#C6ECE9" stroke="#7DBCB7"/>
|
||||
<text x="120" y="66.5" class="c sub b">浏览器</text>
|
||||
<line x1="120" y1="80" x2="120" y2="270" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<rect x="300" y="46" width="140" height="32" rx="6" fill="#EAE9E7" stroke="#BFBEBA"/>
|
||||
<text x="370" y="66.5" class="c sub b">代理 proxy:8080</text>
|
||||
<line x1="370" y1="80" x2="370" y2="270" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<rect x="550" y="46" width="140" height="32" rx="6" fill="#C6E4FB" stroke="#7FB2D6"/>
|
||||
<text x="620" y="66.5" class="c sub b">www.example.com:443</text>
|
||||
<line x1="620" y1="80" x2="620" y2="270" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<line x1="120" y1="110" x2="370" y2="110" class="arrow "/>
|
||||
<text x="245" y="104" class="c sub mono" style="fill:#444">CONNECT www.example.com:443 HTTP/1.1</text>
|
||||
<line x1="370" y1="140" x2="620" y2="140" class="arrow "/>
|
||||
<text x="495" y="134" class="c sub" style="fill:#444">建立 TCP 连接</text>
|
||||
<line x1="370" y1="170" x2="120" y2="170" class="arrow dash"/>
|
||||
<text x="245" y="164" class="c sub mono" style="fill:#444">HTTP/1.1 200 Connection Established</text>
|
||||
<rect x="120" y="196" width="500" height="34" rx="17" fill="#E6E3FA" fill-opacity="0.5" stroke="#B8B0DE"/>
|
||||
<text x="370" y="218" class="c sub" style="fill:#444">TLS 握手和加密的 HTTP 报文,代理只转发字节,看不到内容</text>
|
||||
<text x="30" y="290" class="sub">代理只知道目标主机和端口;之后它像一根管道,把两端的数据原样转发。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,74 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="760" height="330" viewBox="0 0 760 330">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="380" y="28" class="title">短连接、长连接与流水线:请求 3 个资源</text>
|
||||
<text x="108" y="90" class="sub b e" style="fill:#444">短连接</text>
|
||||
<rect x="122" y="70" width="86" height="30" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="165" y="90" class="c sub" style="fill:#444">握手</text>
|
||||
<rect x="212" y="70" width="86" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="255" y="90" class="c sub" style="fill:#444">请求 1</text>
|
||||
<rect x="302" y="70" width="86" height="30" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="345" y="90" class="c sub" style="fill:#444">握手</text>
|
||||
<rect x="392" y="70" width="86" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="435" y="90" class="c sub" style="fill:#444">请求 2</text>
|
||||
<rect x="482" y="70" width="86" height="30" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="525" y="90" class="c sub" style="fill:#444">握手</text>
|
||||
<rect x="572" y="70" width="86" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="615" y="90" class="c sub" style="fill:#444">请求 3</text>
|
||||
<text x="672" y="90" class="sub b" style="fill:#444">6 个 RTT</text>
|
||||
<text x="108" y="156" class="sub b e" style="fill:#444">长连接</text>
|
||||
<rect x="122" y="136" width="86" height="30" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="165" y="156" class="c sub" style="fill:#444">握手</text>
|
||||
<rect x="212" y="136" width="86" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="255" y="156" class="c sub" style="fill:#444">请求 1</text>
|
||||
<rect x="302" y="136" width="86" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="345" y="156" class="c sub" style="fill:#444">请求 2</text>
|
||||
<rect x="392" y="136" width="86" height="30" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="435" y="156" class="c sub" style="fill:#444">请求 3</text>
|
||||
<text x="672" y="156" class="sub b" style="fill:#444">4 个 RTT</text>
|
||||
<text x="108" y="222" class="sub b e" style="fill:#444">流水线</text>
|
||||
<rect x="122" y="202" width="86" height="30" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="165" y="222" class="c sub" style="fill:#444">握手</text>
|
||||
<rect x="212" y="202" width="113" height="30" rx="3" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1"/>
|
||||
<text x="268.5" y="222" class="c sub" style="fill:#444">请求 1、2、3 连续发出</text>
|
||||
<text x="672" y="222" class="sub b" style="fill:#444">约 2 个 RTT</text>
|
||||
<text x="120" y="280" class="c sub mono">0</text>
|
||||
<text x="210" y="280" class="c sub mono">1</text>
|
||||
<text x="300" y="280" class="c sub mono">2</text>
|
||||
<text x="390" y="280" class="c sub mono">3</text>
|
||||
<text x="480" y="280" class="c sub mono">4</text>
|
||||
<text x="570" y="280" class="c sub mono">5</text>
|
||||
<text x="660" y="280" class="c sub mono">6</text>
|
||||
<line x1="120" y1="268" x2="660" y2="268" class="line"/>
|
||||
<text x="660" y="298" class="c sub">RTT</text>
|
||||
<text x="30" y="316" class="sub">灰色是 TCP 三次握手,每段约 1 个 RTT。HTTP/1.1 默认使用长连接;流水线中响应仍需按顺序返回,前一个慢了会阻塞后面的。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
@@ -0,0 +1,109 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="760" height="260" viewBox="0 0 760 260">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="380" y="28" class="title">正向代理与反向代理</text>
|
||||
<rect x="30" y="46" width="350" height="170" rx="8" class="frame"/>
|
||||
<text x="40" y="64" class="b">正向代理</text>
|
||||
<rect x="42" y="78" width="190" height="126" rx="8" fill="#C6ECE9" fill-opacity="0.25"/>
|
||||
<text x="52" y="196" class="sub">内网</text>
|
||||
<rect x="60" y="100" width="40" height="27.2" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<rect x="64" y="104" width="32" height="19.2" rx="1.5" fill="#FFFFFF" stroke="#7FB2D6" stroke-width="0.8"/>
|
||||
<path d="M76,127.2 v5 M84,127.2 v5" stroke="#7FB2D6" stroke-width="1.4"/>
|
||||
<rect x="68" y="132.2" width="24" height="3.5" rx="1.5" fill="#7FB2D6"/>
|
||||
<text x="80" y="150" class="c sub">客户端</text>
|
||||
<rect x="160" y="98" width="40" height="13" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1.2"/>
|
||||
<circle cx="167" cy="104.5" r="2" fill="#BFBEBA"/>
|
||||
<line x1="174" y1="104.5" x2="193" y2="104.5" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<rect x="160" y="114" width="40" height="13" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1.2"/>
|
||||
<circle cx="167" cy="120.5" r="2" fill="#BFBEBA"/>
|
||||
<line x1="174" y1="120.5" x2="193" y2="120.5" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<rect x="160" y="130" width="40" height="13" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1.2"/>
|
||||
<circle cx="167" cy="136.5" r="2" fill="#BFBEBA"/>
|
||||
<line x1="174" y1="136.5" x2="193" y2="136.5" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="180" y="150" class="c sub b">代理</text>
|
||||
<rect x="300" y="98" width="40" height="13" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<circle cx="307" cy="104.5" r="2" fill="#7FB2D6"/>
|
||||
<line x1="314" y1="104.5" x2="333" y2="104.5" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<rect x="300" y="114" width="40" height="13" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<circle cx="307" cy="120.5" r="2" fill="#7FB2D6"/>
|
||||
<line x1="314" y1="120.5" x2="333" y2="120.5" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<rect x="300" y="130" width="40" height="13" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<circle cx="307" cy="136.5" r="2" fill="#7FB2D6"/>
|
||||
<line x1="314" y1="136.5" x2="333" y2="136.5" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="320" y="150" class="c sub">网站</text>
|
||||
<line x1="104" y1="116" x2="156" y2="116" class="arrow "/>
|
||||
<line x1="204" y1="116" x2="296" y2="116" class="arrow "/>
|
||||
<text x="250" y="108" class="c sub">互联网</text>
|
||||
<text x="205" y="236" class="c sub">代理客户端:服务器看到的是代理的地址</text>
|
||||
<rect x="410" y="46" width="350" height="170" rx="8" class="frame"/>
|
||||
<text x="420" y="64" class="b">反向代理</text>
|
||||
<rect x="550" y="78" width="198" height="126" rx="8" fill="#C6E4FB" fill-opacity="0.25"/>
|
||||
<text x="710" y="196" class="sub">机房</text>
|
||||
<rect x="440" y="100" width="40" height="27.2" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<rect x="444" y="104" width="32" height="19.2" rx="1.5" fill="#FFFFFF" stroke="#7FB2D6" stroke-width="0.8"/>
|
||||
<path d="M456,127.2 v5 M464,127.2 v5" stroke="#7FB2D6" stroke-width="1.4"/>
|
||||
<rect x="448" y="132.2" width="24" height="3.5" rx="1.5" fill="#7FB2D6"/>
|
||||
<text x="460" y="150" class="c sub">客户端</text>
|
||||
<rect x="570" y="98" width="40" height="13" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1.2"/>
|
||||
<circle cx="577" cy="104.5" r="2" fill="#BFBEBA"/>
|
||||
<line x1="584" y1="104.5" x2="603" y2="104.5" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<rect x="570" y="114" width="40" height="13" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1.2"/>
|
||||
<circle cx="577" cy="120.5" r="2" fill="#BFBEBA"/>
|
||||
<line x1="584" y1="120.5" x2="603" y2="120.5" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<rect x="570" y="130" width="40" height="13" rx="3" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1.2"/>
|
||||
<circle cx="577" cy="136.5" r="2" fill="#BFBEBA"/>
|
||||
<line x1="584" y1="136.5" x2="603" y2="136.5" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="590" y="150" class="c sub b">Nginx</text>
|
||||
<rect x="693" y="82" width="34" height="13" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<circle cx="700" cy="88.5" r="2" fill="#7FB2D6"/>
|
||||
<line x1="707" y1="88.5" x2="720" y2="88.5" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<rect x="693" y="98" width="34" height="13" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<circle cx="700" cy="104.5" r="2" fill="#7FB2D6"/>
|
||||
<line x1="707" y1="104.5" x2="720" y2="104.5" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<rect x="693" y="120" width="34" height="13" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<circle cx="700" cy="126.5" r="2" fill="#7FB2D6"/>
|
||||
<line x1="707" y1="126.5" x2="720" y2="126.5" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<rect x="693" y="136" width="34" height="13" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<circle cx="700" cy="142.5" r="2" fill="#7FB2D6"/>
|
||||
<line x1="707" y1="142.5" x2="720" y2="142.5" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<rect x="693" y="158" width="34" height="13" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<circle cx="700" cy="164.5" r="2" fill="#7FB2D6"/>
|
||||
<line x1="707" y1="164.5" x2="720" y2="164.5" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<rect x="693" y="174" width="34" height="13" rx="3" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1.2"/>
|
||||
<circle cx="700" cy="180.5" r="2" fill="#7FB2D6"/>
|
||||
<line x1="707" y1="180.5" x2="720" y2="180.5" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<line x1="484" y1="116" x2="566" y2="116" class="arrow "/>
|
||||
<line x1="614" y1="116" x2="690" y2="92" class="arrow "/>
|
||||
<line x1="614" y1="116" x2="690" y2="130" class="arrow "/>
|
||||
<line x1="614" y1="116" x2="690" y2="168" class="arrow "/>
|
||||
<text x="585" y="236" class="c sub">代理服务器:客户端只知道代理的地址</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.3 KiB |
@@ -0,0 +1,51 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="740" height="300" viewBox="0 0 740 300">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="370" y="28" class="title">混合加密:用非对称加密传递会话密钥(TLS 1.2 的 RSA 密钥交换)</text>
|
||||
<rect x="80" y="46" width="140" height="32" rx="6" fill="#C6ECE9" stroke="#7DBCB7"/>
|
||||
<text x="150" y="66.5" class="c sub b">浏览器</text>
|
||||
<line x1="150" y1="80" x2="150" y2="270" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<rect x="520" y="46" width="140" height="32" rx="6" fill="#C6E4FB" stroke="#7FB2D6"/>
|
||||
<text x="590" y="66.5" class="c sub b">服务器(持有私钥)</text>
|
||||
<line x1="590" y1="80" x2="590" y2="270" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<line x1="150" y1="110" x2="590" y2="110" class="arrow "/>
|
||||
<text x="370" y="104" class="c sub" style="fill:#444">① 客户端随机数</text>
|
||||
<line x1="590" y1="144" x2="150" y2="144" class="arrow dash"/>
|
||||
<text x="370" y="138" class="c sub" style="fill:#444">② 服务器随机数 + 证书(含公钥)</text>
|
||||
<line x1="150" y1="178" x2="590" y2="178" class="arrow "/>
|
||||
<text x="370" y="172" class="c sub" style="fill:#444">③ 用公钥加密的预主密钥</text>
|
||||
<text x="138" y="210" class="sub e" style="fill:#766AA8">三者算出会话密钥</text>
|
||||
<text x="602" y="210" class="sub" style="fill:#766AA8">解密后算出同样的会话密钥</text>
|
||||
<rect x="150" y="226" width="440" height="30" rx="15" fill="#E6E3FA" fill-opacity="0.5" stroke="#B8B0DE"/>
|
||||
<text x="370" y="246" class="c sub" style="fill:#444">④ 之后的 HTTP 报文用会话密钥对称加密(例如 AES-GCM)</text>
|
||||
<text x="30" y="290" class="sub">这种方式下私钥一旦泄露,之前录下的通信都能被解密,TLS 1.3 已经去掉它,改用 ECDHE 密钥交换。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,62 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="280" viewBox="0 0 720 280">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="360" y="28" class="title">HTTPS:HTTP 报文交给 TLS 加密后再交给 TCP</text>
|
||||
<text x="120" y="56" class="c b">HTTP</text>
|
||||
<rect x="60" y="66" width="120" height="32" rx="4" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="120" y="86" class="c sub b" style="fill:#444">HTTP</text>
|
||||
<rect x="60" y="104" width="120" height="32" rx="4" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="120" y="124" class="c sub b" style="fill:#444">TCP</text>
|
||||
<rect x="60" y="142" width="120" height="32" rx="4" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="120" y="162" class="c sub b" style="fill:#444">IP</text>
|
||||
<text x="300" y="56" class="c b">HTTPS</text>
|
||||
<rect x="240" y="66" width="120" height="32" rx="4" fill="#C6E4FB" stroke="#7FB2D6" stroke-width="1"/>
|
||||
<text x="300" y="86" class="c sub b" style="fill:#444">HTTP</text>
|
||||
<rect x="240" y="104" width="120" height="32" rx="4" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1"/>
|
||||
<text x="300" y="124" class="c sub b" style="fill:#444">TLS</text>
|
||||
<rect x="240" y="142" width="120" height="32" rx="4" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="300" y="162" class="c sub b" style="fill:#444">TCP</text>
|
||||
<rect x="240" y="180" width="120" height="32" rx="4" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="300" y="200" class="c sub b" style="fill:#444">IP</text>
|
||||
<text x="420" y="60" class="b">抓包能看到的内容</text>
|
||||
<rect x="420" y="72" width="270" height="36" rx="4" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="430" y="87" class="sub b" style="fill:#444">IP、TCP 首部</text>
|
||||
<text x="430" y="102" class="sub">明文:双方的地址和端口</text>
|
||||
<rect x="420" y="116" width="270" height="36" rx="4" fill="#EAE9E7" stroke="#BFBEBA" stroke-width="1"/>
|
||||
<text x="430" y="131" class="sub b" style="fill:#444">TLS 记录头</text>
|
||||
<text x="430" y="146" class="sub">明文:类型、版本、长度</text>
|
||||
<rect x="420" y="160" width="270" height="36" rx="4" fill="#E6E3FA" stroke="#B8B0DE" stroke-width="1"/>
|
||||
<text x="430" y="175" class="sub b" style="fill:#444">HTTP 请求行、首部、主体</text>
|
||||
<text x="430" y="190" class="sub">全部加密,包括 URL 和 Cookie</text>
|
||||
<text x="30" y="240" class="sub">HTTPS 默认端口 443。握手时 ClientHello 中的 SNI(要访问的域名)仍是明文,</text>
|
||||
<text x="30" y="258" class="sub">所以中间人能知道访问的是哪个网站,但看不到访问了哪个页面、提交了什么内容。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
@@ -0,0 +1,64 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="760" height="560" viewBox="0 0 760 560">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="380" y="28" class="title">OAuth 2.0 授权码流程:令牌由后端换取,不经过浏览器</text>
|
||||
<rect x="10" y="52" width="200" height="32" rx="6" fill="#E6E3FA" stroke="#B8B0DE"/>
|
||||
<text x="110" y="72.5" class="c sub b">用户的浏览器</text>
|
||||
<line x1="110" y1="84" x2="110" y2="520" stroke="#C8C8C8" stroke-dasharray="4 3"/>
|
||||
<rect x="280" y="52" width="200" height="32" rx="6" fill="#C6ECE9" stroke="#7DBCB7"/>
|
||||
<text x="380" y="72.5" class="c sub b">笔记网站 notes.example.com</text>
|
||||
<line x1="380" y1="84" x2="380" y2="520" stroke="#C8C8C8" stroke-dasharray="4 3"/>
|
||||
<rect x="550" y="52" width="200" height="32" rx="6" fill="#C6E4FB" stroke="#7FB2D6"/>
|
||||
<text x="650" y="72.5" class="c sub b">授权服务器 id.example.com</text>
|
||||
<line x1="650" y1="84" x2="650" y2="520" stroke="#C8C8C8" stroke-dasharray="4 3"/>
|
||||
<line x1="114" y1="116" x2="374" y2="116" class="arrow "/>
|
||||
<text x="245" y="109" class="c sub">① 点击“用账号中心登录”</text>
|
||||
<line x1="376" y1="160" x2="116" y2="160" class="arrow "/>
|
||||
<text x="245" y="153" class="c sub">② 302 到 id.example.com/authorize</text>
|
||||
<text x="245" y="174" class="c sub">带上 state 和 code_challenge</text>
|
||||
<line x1="114" y1="218" x2="644" y2="218" class="arrow "/>
|
||||
<text x="128" y="211" class="sub">③ GET /authorize,用户登录并点击同意</text>
|
||||
<line x1="646" y1="262" x2="116" y2="262" class="arrow "/>
|
||||
<text x="128" y="255" class="sub">④ 302 到 notes.example.com/callback</text>
|
||||
<text x="128" y="276" class="sub mono">?code=R9Ydi...&state=x7Kp2</text>
|
||||
<line x1="114" y1="320" x2="374" y2="320" class="arrow "/>
|
||||
<text x="245" y="313" class="c sub">⑤ GET /callback?code=R9Ydi...&state=x7Kp2</text>
|
||||
<line x1="384" y1="364" x2="644" y2="364" class="arrow green"/>
|
||||
<text x="515" y="357" class="c sub ok">⑥ POST /token:code + code_verifier</text>
|
||||
<line x1="646" y1="408" x2="386" y2="408" class="arrow green"/>
|
||||
<text x="515" y="401" class="c sub ok">⑦ {"access_token": "v-7Dl...", "expires_in": 3600}</text>
|
||||
<line x1="384" y1="452" x2="644" y2="452" class="arrow green"/>
|
||||
<text x="515" y="445" class="c sub ok">⑧ GET /userinfo,Authorization: Bearer v-7Dl...</text>
|
||||
<line x1="376" y1="496" x2="116" y2="496" class="arrow "/>
|
||||
<text x="245" y="489" class="c sub">⑨ 登录成功,Set-Cookie: 笔记网站自己的会话</text>
|
||||
<text x="24" y="540" class="sub">绿色是笔记网站后端与授权服务器之间的直接请求,访问令牌不经过浏览器;授权码经过浏览器,但只能用一次,换令牌时还要提供 code_verifier。</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
@@ -0,0 +1,82 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="760" height="470" viewBox="0 0 760 470">
|
||||
<style>
|
||||
text { font-family: "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif; fill: #3F3F3F; font-size: 12px; }
|
||||
.title { font-weight: bold; font-size: 15px; fill: #333; text-anchor: middle; }
|
||||
.b { font-weight: bold; }
|
||||
.c { text-anchor: middle; }
|
||||
.e { text-anchor: end; }
|
||||
.sub { font-size: 11px; fill: #6E6E6E; }
|
||||
.note { fill: #C0605A; }
|
||||
.ok { fill: #6A9F68; }
|
||||
.mono { font-family: Menlo, Consolas, monospace; }
|
||||
.arrow { stroke: #555; stroke-width: 1.1; fill: none; marker-end: url(#a); }
|
||||
.red { stroke: #C0605A; marker-end: url(#r); }
|
||||
.green { stroke: #6A9F68; marker-end: url(#g); }
|
||||
.dash { stroke-dasharray: 5 4; }
|
||||
.line { stroke: #555; stroke-width: 1.1; fill: none; }
|
||||
.frame { fill: none; stroke: #999; stroke-width: 1; stroke-dasharray: 4 3; }
|
||||
.shadow { fill: #DADADA; }
|
||||
</style>
|
||||
<defs>
|
||||
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#555"/>
|
||||
</marker>
|
||||
<marker id="r" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#C0605A"/>
|
||||
</marker>
|
||||
<marker id="g" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M1,1.5 L9.5,5 L1,8.5 z" fill="#6A9F68"/>
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
|
||||
<text x="380" y="28" class="title">TLS 1.2 与 TLS 1.3 的握手(本机 openssl 实测的报文顺序)</text>
|
||||
<text x="200" y="58" class="c b">TLS 1.2:www.baidu.com</text>
|
||||
<line x1="70" y1="70" x2="70" y2="420" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<line x1="330" y1="70" x2="330" y2="420" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<text x="70" y="432" class="c sub">客户端</text>
|
||||
<text x="330" y="432" class="c sub">服务器</text>
|
||||
<line x1="70" y1="86" x2="330" y2="86" class="arrow "/>
|
||||
<text x="200" y="81" class="c sub mono" style="fill:#444">ClientHello</text>
|
||||
<line x1="330" y1="128" x2="70" y2="128" class="arrow dash"/>
|
||||
<text x="200" y="123" class="c sub mono" style="fill:#444">ServerHello</text>
|
||||
<line x1="330" y1="160" x2="70" y2="160" class="arrow dash"/>
|
||||
<text x="200" y="155" class="c sub mono" style="fill:#444">Certificate</text>
|
||||
<line x1="330" y1="192" x2="70" y2="192" class="arrow dash"/>
|
||||
<text x="200" y="187" class="c sub mono" style="fill:#444">ServerKeyExchange</text>
|
||||
<text x="200" y="204" class="c sub">ECDHE 公钥 + 签名</text>
|
||||
<line x1="330" y1="236" x2="70" y2="236" class="arrow dash"/>
|
||||
<text x="200" y="231" class="c sub mono" style="fill:#444">ServerHelloDone</text>
|
||||
<line x1="70" y1="278" x2="330" y2="278" class="arrow "/>
|
||||
<text x="200" y="273" class="c sub mono" style="fill:#444">ClientKeyExchange</text>
|
||||
<text x="200" y="290" class="c sub">ECDHE 公钥</text>
|
||||
<line x1="70" y1="322" x2="330" y2="322" class="arrow "/>
|
||||
<text x="200" y="317" class="c sub mono" style="fill:#444">ChangeCipherSpec, Finished</text>
|
||||
<line x1="330" y1="364" x2="70" y2="364" class="arrow dash"/>
|
||||
<text x="200" y="359" class="c sub mono" style="fill:#444">ChangeCipherSpec, Finished</text>
|
||||
<line x1="70" y1="406" x2="330" y2="406" class="arrow green"/>
|
||||
<text x="200" y="401" class="c sub mono" style="fill:#444">HTTP 请求(加密)</text>
|
||||
<text x="200" y="452" class="c sub b" style="fill:#296898">2 个 RTT 后才能发送请求</text>
|
||||
<text x="570" y="58" class="c b">TLS 1.3:www.example.com</text>
|
||||
<line x1="440" y1="70" x2="440" y2="420" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<line x1="700" y1="70" x2="700" y2="420" stroke="#BBB" stroke-dasharray="4 4"/>
|
||||
<text x="440" y="432" class="c sub">客户端</text>
|
||||
<text x="700" y="432" class="c sub">服务器</text>
|
||||
<line x1="440" y1="86" x2="700" y2="86" class="arrow "/>
|
||||
<text x="570" y="81" class="c sub mono" style="fill:#444">ClientHello + key_share</text>
|
||||
<text x="570" y="98" class="c sub">带上 ECDHE 公钥</text>
|
||||
<line x1="700" y1="140" x2="440" y2="140" class="arrow dash"/>
|
||||
<text x="570" y="135" class="c sub mono" style="fill:#444">ServerHello + key_share</text>
|
||||
<line x1="700" y1="172" x2="440" y2="172" class="arrow dash"/>
|
||||
<text x="570" y="167" class="c sub mono" style="fill:#444">{EncryptedExtensions}</text>
|
||||
<line x1="700" y1="204" x2="440" y2="204" class="arrow dash"/>
|
||||
<text x="570" y="199" class="c sub mono" style="fill:#444">{Certificate}</text>
|
||||
<line x1="700" y1="236" x2="440" y2="236" class="arrow dash"/>
|
||||
<text x="570" y="231" class="c sub mono" style="fill:#444">{CertificateVerify}</text>
|
||||
<text x="570" y="248" class="c sub">用私钥签名</text>
|
||||
<line x1="700" y1="280" x2="440" y2="280" class="arrow dash"/>
|
||||
<text x="570" y="275" class="c sub mono" style="fill:#444">{Finished}</text>
|
||||
<line x1="440" y1="322" x2="700" y2="322" class="arrow green"/>
|
||||
<text x="570" y="317" class="c sub mono" style="fill:#444">{Finished} + HTTP 请求</text>
|
||||
<text x="570" y="452" class="c sub b" style="fill:#296898">1 个 RTT 后就能发送请求</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |