掌握 Web 通信协议与安全机制
请求行(Request Line)
GET /api/users HTTP/1.1
请求头(Request Headers)
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: application/json
Content-Type: application/json
Cookie: session_id=abc123
空行(CRLF)
请求体(Request Body)- 可选
{"username": "john", "password": "123456"}状态行(Status Line)
HTTP/1.1 200 OK
响应头(Response Headers)
Content-Type: application/json
Content-Length: 1234
Set-Cookie: session_id=xyz789
Cache-Control: max-age=3600
空行(CRLF)
响应体(Response Body)
{"id": 1, "name": "John Doe"}| 方法 | 幂等性 | 安全性 | 可缓存 | 用途 |
|---|---|---|---|---|
| GET | ✓ | ✓ | ✓ | 获取资源 |
| POST | ✗ | ✗ | 部分 | 创建资源、提交数据 |
| PUT | ✓ | ✗ | ✗ | 更新资源(完整替换) |
| PATCH | ✗ | ✗ | ✗ | 部分更新资源 |
| DELETE | ✓ | ✗ | ✗ | 删除资源 |
| HEAD | ✓ | ✓ | ✓ | 获取响应头(不返回 body) |
| OPTIONS | ✓ | ✓ | ✗ | 查询支持的方法(CORS 预检) |
GET /users # 获取用户列表
GET /users/123 # 获取单个用户
POST /users # 创建用户
PUT /users/123 # 完整更新用户
PATCH /users/123 # 部分更新用户
DELETE /users/123 # 删除用户| 特性 | GET | POST |
|---|---|---|
| 参数位置 | URL 查询字符串 | 请求体 |
| 长度限制 | 有(浏览器/服务器限制) | 无(理论上) |
| 可见性 | URL 可见,不安全 | 相对安全 |
| 缓存 | 可缓存 | 默认不缓存 |
| 书签 | 可保存为书签 | 不可以 |
| 历史记录 | 保留在浏览器历史 | 不保留 |
| 状态码 | 含义 | 说明 |
|---|---|---|
| 200 | OK | 请求成功 |
| 201 | Created | 资源创建成功(POST) |
| 204 | No Content | 成功但无返回内容(DELETE) |
| 301 | Moved Permanently | 永久重定向 |
| 302 | Found | 临时重定向 |
| 304 | Not Modified | 资源未修改,使用缓存 |
| 400 | Bad Request | 请求语法错误 |
| 401 | Unauthorized | 未认证(需要登录) |
| 403 | Forbidden | 无权限访问 |
| 404 | Not Found | 资源不存在 |
| 405 | Method Not Allowed | 方法不允许 |
| 429 | Too Many Requests | 请求过多(限流) |
| 500 | Internal Server Error | 服务器内部错误 |
| 502 | Bad Gateway | 网关错误 |
| 503 | Service Unavailable | 服务不可用 |
| 504 | Gateway Timeout | 网关超时 |
| 特性 | HTTP/1.0 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|---|
| 发布年份 | 1996 | 1999 | 2015 | 2022 |
| 连接 | 短连接 | 长连接 | 多路复用 | 多路复用 |
| 传输协议 | TCP | TCP | TCP | UDP (QUIC) |
| 头部压缩 | ✗ | ✗ | HPACK | QPACK |
| 服务器推送 | ✗ | ✗ | ✓ | ✓ |
| 队头阻塞 | 有 | 有 | 有(TCP 层) | 无 |
# HTTP/1.1 - 多个请求需要多个连接或串行
Connection 1: GET /index.html
Connection 2: GET /style.css
Connection 3: GET /script.js
# HTTP/2 - 一个连接并发处理
Connection 1:
Stream 1: GET /index.html
Stream 2: GET /style.css
Stream 3: GET /script.jsHTTP/2 解决了应用层的队头阻塞,但 TCP 层仍存在:
HTTPS 在 HTTP 和 TCP 之间加入 SSL/TLS 层,提供加密、认证和完整性保护。
# TLS 1.2 握手(简化)
Client Server
| |
|--- Client Hello ------------------> |
| |
|<-- Server Hello -------------------| |
|<-- Certificate --------------------| |
|<-- Server Hello Done --------------| |
| |
|--- Client Key Exchange -----------> |
|--- Change Cipher Spec ------------> |
|--- Finished -----------------------> |
| |
|<-- Change Cipher Spec -------------| |
|<-- Finished -----------------------| |
| |
|<-- Encrypted Application Data ----> |# TLS 1.3 握手(1-RTT)
Client Server
| |
|--- Client Hello ------------------> |
| (包含密钥交换参数) |
| |
|<-- Server Hello -------------------| |
|<-- Certificate --------------------| |
|<-- Finished -----------------------| |
| |
|--- Finished -----------------------> |
| |
|<-- Encrypted Application Data ----> || 特性 | Cookie | Session | Token (JWT) |
|---|---|---|---|
| 存储位置 | 客户端(浏览器) | 服务器 | 客户端 |
| 数据大小 | 4KB 限制 | 无限制 | 较大(包含用户信息) |
| 安全性 | 较低(可被窃取) | 较高 | 中等(需防止泄露) |
| 跨域 | 受同源策略限制 | 受限 | 支持 |
| 服务器压力 | 无 | 需存储 | 无 |
| 扩展性 | 好 | 差(需共享存储) | 好 |
# 服务器设置 Cookie
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Strict
# 浏览器自动携带 Cookie
Cookie: session_id=abc123Cookie 属性:
Session 存储方案:
# JWT 格式:Header.Payload.Signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
# Header(Base64 编码)
{
"alg": "HS256",
"typ": "JWT"
}
# Payload(Base64 编码)
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
}
# Signature(签名)
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)JWT 优点:
JWT 缺点:
# Expires(HTTP/1.0,已过时)
Expires: Wed, 21 Oct 2025 07:28:00 GMT
# Cache-Control(HTTP/1.1,推荐)
Cache-Control: max-age=3600 # 缓存 3600 秒
Cache-Control: no-cache # 需要协商缓存
Cache-Control: no-store # 完全不缓存
Cache-Control: public # 可被任何缓存存储
Cache-Control: private # 只能被浏览器缓存Cache-Control 指令:
方式一:Last-Modified / If-Modified-Since
# 首次请求
Response:
Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT
# 再次请求
Request:
If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT
# 未修改
Response:
304 Not Modified
# 已修改
Response:
200 OK
Last-Modified: Wed, 21 Oct 2024 08:00:00 GMT
(新内容)方式二:ETag / If-None-Match(更精确)
# 首次请求
Response:
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
# 再次请求
Request:
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
# 未修改
Response:
304 Not Modified# Nginx 配置
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d; # 静态资源缓存 30 天
add_header Cache-Control "public, immutable";
}
location ~* \.(html)$ {
expires -1; # HTML 不缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
}浏览器安全机制,限制不同源之间的资源访问。
同源定义:协议、域名、端口完全相同
# 同源
http://example.com/page1
http://example.com/page2
# 不同源
http://example.com vs https://example.com (协议不同)
http://example.com vs http://api.example.com (域名不同)
http://example.com:80 vs http://example.com:8080 (端口不同)跨域资源共享,通过 HTTP 头部允许跨域访问。
满足以下条件的请求:
# 请求
GET /api/data HTTP/1.1
Origin: http://example.com
# 响应
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Credentials: true非简单请求会先发送 OPTIONS 请求:
# 预检请求
OPTIONS /api/data HTTP/1.1
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type
# 预检响应
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400 # 缓存预检结果 24 小时
# 实际请求
PUT /api/data HTTP/1.1
Origin: http://example.com
Content-Type: application/json// Spring Boot CORS 配置
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
};
}
}

# 客户端请求
GET /index.html HTTP/1.1
Host: www.example.com
Connection: keep-alive
# 服务器响应
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=100timeout:连接空闲多长时间后关闭。max:一个连接最多复用多少个请求。Upgrade: websocket 头升级协议。| 维度 | HTTP | WebSocket |
|---|---|---|
| 通信模式 | 请求-响应 | 双向实时通信 |
| 连接 | 短连接/长连接 | 长连接 |
| 消息方向 | 通常由客户端发起 | 任意一方可主动发送 |
| 典型场景 | 普通页面、REST API | IM、实时推送、协同编辑 |
// 浏览器端示例
const ws = new WebSocket('wss://example.com/ws');
ws.onopen = () => ws.send('hello');
ws.onmessage = (evt) => console.log('msg:', evt.data);
ws.onclose = () => console.log('closed');innerHTML。HttpOnly,防止被脚本读取。SameSite=Lax/Strict,减少第三方请求自动携带 Cookie。X-Frame-Options / frame-ancestors 防止点击劫持。面试时可以结合自己项目的安全加固实践来讲,例如「统一接入 WAF、防爬限流、登录网关与单点登录」等,会比单纯背诵概念更有说服力。