1990 年,Tim Berners-Lee 在 CERN 发明了万维网(WWW),同时设计了 HTTP/0.9——一个极其简单的协议:客户端发送 GET 请求,服务器返回 HTML 文件,没有请求头、响应头、状态码。随着 Web 的迅速普及,HTTP 需要支持更多的功能:内容类型、缓存控制、身份认证、连接复用等。
HTTP/1.0 (1996): 引入版本号、状态码、请求头、响应头、内容类型(Content-Type)。每个请求建立一个新的 TCP 连接,即短连接——请求完成后立即关闭。
HTTP/1.1 (1997): 引入持久连接 (Keep-Alive),允许在同一个 TCP 连接上发送多个请求和响应;增加管道化 (Pipelining),允许客户端连续发送多个请求而不等待响应;增加分块传输编码 (Chunked Transfer Encoding),支持动态内容。
HTTP/2.0 (2015): 基于 SPDY 协议,引入二进制分帧、多路复用、头部压缩 (HPACK)、服务器推送。解决了 HTTP/1.1 的队头阻塞问题。
HTTP/3.0 (2022): 基于 QUIC 协议(UDP 之上),解决 HTTP/2.0 在传输层的队头阻塞问题,减少连接建立延迟,支持 0-RTT 快速连接。
# HTTP/1.1 请求示例 (顺序发送,队头阻塞)
GET /image1.jpg HTTP/1.1
Host: example.com
GET /image2.jpg HTTP/1.1
Host: example.com
GET /image3.jpg HTTP/1.1
Host: example.com
# HTTP/2.0 帧结构 (二进制分帧,多路复用)
# 每个请求/响应被拆分为帧,通过流 ID 标识
# 帧类型: HEADERS, DATA, SETTINGS, PRIORITY 等
# 不同流的帧交错发送,无队头阻塞
# 使用 curl 查看 HTTP/2.0 支持
curl --http2 -I https://example.com
HTTP 采用 客户端-服务器 架构,通信模式为 请求-响应 模型:客户端(通常是浏览器)发起请求,服务器接收请求、处理后返回响应。这种模型简单、明确,但也带来了服务器无法主动推送的限制(虽然 HTTP/2 的服务器推送解决了部分问题)。
请求报文结构:
响应报文结构:
常用请求方法:
# 请求报文
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 45
User-Agent: Mozilla/5.0
{
"name": "张三",
"age": 28
}
# 响应报文
HTTP/1.1 201 Created
Location: /api/users/12345
Content-Type: application/json
Content-Length: 30
{
"id": "12345",
"name": "张三"
}
HTTP 是无状态协议,服务器不会在请求之间保存客户端的状态。但 Web 应用需要跟踪用户,例如购物车、登录状态、用户偏好。Cookie 和 Session 是解决这个问题的两种核心机制:Cookie 在客户端存储状态,Session 在服务器存储状态。
Cookie 属性:
Session 管理: Session 数据存储在服务器,通过 Cookie 传递 Session ID。Session ID 通常使用 Secure 和 HttpOnly 的 Cookie 来保护。Session 的存储方式可以是内存、Redis、数据库等。
// 设置 Cookie (服务器端)
res.setHeader('Set-Cookie', [
'user_id=12345; Max-Age=3600; Secure; HttpOnly',
'session_id=abcde12345; Secure; HttpOnly; SameSite=Strict'
]);
// 读取 Cookie (客户端 JavaScript)
// 如果 HttpOnly 被设置,JavaScript 无法读取
console.log(document.cookie); // 只显示非 HttpOnly 的 Cookie
// Session 管理示例 (使用 express-session)
const session = require('express-session');
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: false,
cookie: { secure: true, httpOnly: true, maxAge: 3600000 }
}));
// 在请求中访问 Session
app.get('/profile', (req, res) => {
if (req.session.user) {
res.json(req.session.user);
} else {
res.status(401).send('未登录');
}
});
Web 页面包含大量资源(图片、CSS、JS),如果每个资源每次都要从服务器重新下载,将导致页面加载缓慢、服务器负载过高。HTTP 缓存通过在客户端和服务器之间引入缓存层,将资源存储在浏览器或中间代理中,大大减少重复请求。
强缓存: 浏览器在缓存有效期内直接使用本地缓存,不发送任何请求。由 Expires 和 Cache-Control: max-age 控制。
协商缓存: 缓存已过期,浏览器向服务器发送验证请求,由服务器决定是否使用缓存。由 Last-Modified/If-Modified-Since 和 ETag/If-None-Match 控制。
# 强缓存:max-age 指令
Cache-Control: public, max-age=86400
# 含义:缓存 24 小时,中间代理和浏览器均可缓存
# 不缓存
Cache-Control: no-cache, no-store, must-revalidate
# no-cache:每次需验证;no-store:完全不缓存
# 协商缓存:ETag 和 Last-Modified
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
# 客户端验证头
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT
互联网是公开的,数据在传输过程中可能被窃听、篡改。如何在不安全的网络上建立安全的通信信道?加密技术提供了解决方案。但加密本身面临一个核心问题:如何安全地交换密钥? 对称加密高效但密钥分发困难,非对称加密解决密钥交换问题但性能较差。
对称加密 (Symmetric Encryption): 加密和解密使用同一个密钥。常见算法:AES (Advanced Encryption Standard)、ChaCha20。
非对称加密 (Asymmetric Encryption): 加密和解密使用不同的密钥(公钥和私钥)。常见算法:RSA、ECDSA (Elliptic Curve)。
数字签名: 用私钥对消息哈希进行加密,验证者用公钥解密和验证,确保消息完整性和来源可信。
# 对称加密 (AES-256)
# 加密:使用密码派生密钥
openssl enc -aes-256-cbc -salt -in plain.txt -out cipher.txt
# 非对称加密 (RSA)
# 生成密钥对
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
# 使用公钥加密
openssl rsautl -encrypt -pubin -inkey public.pem -in plain.txt -out cipher.txt
# 使用私钥解密
openssl rsautl -decrypt -inkey private.pem -in cipher.txt -out plain.txt
HTTPS = HTTP + TLS(Transport Layer Security)。TLS 是 SSL 的后继者,在传输层提供加密、认证和完整性保护。TLS 握手是 HTTPS 连接建立的关键阶段,负责身份验证(服务器证书验证)、密钥协商(生成会话密钥)、密码套件协商(选择加密算法)。
TLS 1.2 完整握手 (4 步):
TLS 1.3 改进:
# 查看 TLS 握手详细信息
openssl s_client -connect example.com:443 -tls1_2
# 使用 TLS 1.3 连接
openssl s_client -connect example.com:443 -tls1_3
# 查看证书链
openssl s_client -connect example.com:443 -showcerts
# 使用 curl 查看 TLS 版本
curl -v https://example.com
# 输出中包含: * TLS version: TLSv1.3
在 TLS 握手中,服务器需要向客户端证明自己的身份。单纯使用公钥是不够的——任何人都可以生成密钥对。需要可信第三方 (CA, Certificate Authority) 对服务器的公钥进行签名认证。证书链是从根 CA 到服务器证书的一条信任链,每一级证书都经过上一级 CA 的签名。
X.509 证书结构:
证书吊销机制:
# 查看证书链 (使用 OpenSSL)
openssl s_client -connect example.com:443 -showcerts
# 查看证书详细信息
openssl x509 -in certificate.pem -text -noout
# 查看 OCSP 状态
openssl ocsp -issuer issuer.pem -cert server.pem -url http://ocsp.example.com
# 使用 curl 查看证书信息
curl -v https://example.com 2>&1 | grep -A 10 "Server certificate"