HTTP 协议

1. HTTP 协议简介

HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最广泛的协议之一,用于客户端和服务器之间的通信。

1.1. HTTP 基础概念

  • 无状态协议:默认不保留客户端状态,每次请求独立(但可通过Cookie/Session模拟状态)。
  • 请求-响应模型:客户端发送请求,服务器返回响应。
  • 基于TCP/IP:默认端口80(HTTP)或443(HTTPS)。
  • 明文传输:HTTP本身不加密,安全性依赖HTTPS(HTTP + TLS/SSL)。

1.2. HTTP 消息结构

请求报文

GET /index.html HTTP/1.1       # 请求行(方法 + URI + 协议版本)
Host: www.example.com          # 必需头部(HTTP/1.1)
User-Agent: Mozilla/5.0        # 客户端信息
Accept: text/html              # 可接受的响应类型
Connection: keep-alive         # 长连接选项
[空行]                         # 分隔头部与主体
[请求体]                       # GET无请求体,POST/PUT有
Bash

响应报文

HTTP/1.1 200 OK                # 状态行(协议版本 + 状态码 + 描述)
Server: nginx/1.18             # 服务器信息
Content-Type: text/html        # 响应体类型
Content-Length: 1024           # 响应体大小
[空行]                         # 分隔头部与主体
<!DOCTYPE html>                # 响应体(如HTML/JSON等)
...
Bash

1.3. HTTP 请求方法

方法作用幂等性安全性
GET获取资源
POST提交数据(创建/更新)
PUT替换整个资源
PATCH部分更新资源
DELETE删除资源
HEAD获取响应头(无Body)
OPTIONS查询服务器支持的HTTP方法

幂等性:多次请求效果相同(如GET、PUT、DELETE)。
安全性:不修改服务器数据(如GET、HEAD)。

1.4. HTTP 状态码

分类常见状态码描述
1xx100 Continue客户端应继续发送请求体
2xx200 OK请求成功
201 Created资源已创建(POST/PUT)
204 No Content响应无Body(如DELETE成功)
3xx301 Moved Permanently永久重定向(更新书签)
302 Found临时重定向(不更新书签)
304 Not Modified资源未修改(缓存有效)
4xx400 Bad Request请求语法错误
401 Unauthorized需身份认证
403 Forbidden服务器拒绝访问
404 Not Found资源不存在
5xx500 Internal Server Error服务器内部错误
502 Bad Gateway网关/代理错误
503 Service Unavailable服务不可用(过载/维护)

1.5. HTTP/1.1 的高级特性

持久连接(Keep-Alive)

  • HTTP 1.1 默认开启长连接,即 TCP 连接默认不会关闭,可以被多个 HTTP 请求和响应复用,减少了创建和关闭连接的消耗和延迟。
  • 在 HTTP 1.0 中使用长连接需要添加请求头 Connection: Keep-Alive,而在HTTP 1.1 中所有的连接默认都是长连接,除非特殊声明不使用长连接( HTTP 请求报文首部加上 Connection: close )。

2. HTTP 协议工作流程

  • 用户输入URL并触发请求
    • 用户在浏览器地址栏输入URL(如http://www.example.com),或点击链接/提交表单。
    • 浏览器解析URL,提取协议(HTTP/HTTPS)、域名www.example.com)、端口(默认80/443)、路径(如/index.html)和查询参数(如?id=123)。
  • DNS解析
    • 浏览器检查本地缓存(Hosts文件、浏览器缓存、系统缓存)是否有域名对应的IP地址。
    • 若未命中缓存,向DNS服务器发起递归查询,最终获取域名对应的IP(如93.184.216.34)。
  • 建立TCP连接(三次握手)
    • 步骤
      • 客户端发送SYN=1, seq=x报文到服务器。
      • 服务器回复SYN=1, ACK=1, seq=y, ack=x+1
      • 客户端发送ACK=1, seq=x+1, ack=y+1
    • 连接建立后,进入数据传输阶段
    • HTTPS额外步骤:在TCP握手后,进行TLS握手(交换证书、协商密钥等)。
  • 发送HTTP请求
  • 服务器处理请求
  • 服务器返回HTTP响应
  • 浏览器渲染页面
  • 断开连接(四次挥手)
    • 默认HTTP/1.1使用Connection: keep-alive复用连接,无需立即关闭。
    • 关闭连接步骤:
      • 客户端发送FIN=1, seq=u
      • 服务器回复ACK=1, ack=u+1
      • 服务器发送FIN=1, seq=v
      • 客户端回复ACK=1, ack=v+1

3. HTTP 协议会话保持

HTTP 协议本身是无状态的,但实际业务中常需要保持用户会话(如登录状态)。以下是实现 HTTP 会话保持 的常见方法及详细说明:

3.1. Cookie(客户端存储)

原理

服务器通过响应头 Set-Cookie 向客户端(浏览器)写入键值对数据,后续请求浏览器自动通过 Cookie 请求头携带该数据。

示例流程

  • 服务器设置Cookie
HTTP/1.1 200 OK
Set-Cookie: session_id=abc123; Path=/; Expires=Wed, 19 Jun 2025 10:00:00 GMT; HttpOnly; Secure


# HttpOnly:禁止JavaScript访问(防XSS)。
# Secure:仅通过HTTPS传输。
# SameSite:限制跨站请求(防CSRF)。
Bash
  • 客户端发送Cookie
GET /dashboard HTTP/1.1
Cookie: session_id=abc123
Bash

Cookie 机制的缺陷:

  • Cookie 信息通过明文的方式储存,容易泄露。
  • Cookie 数据在客户端存储,可能被恶意程序(如 XSS 攻击)窃取。

为了弥补使用 Cookie 而造成的安全问题,引入了 Session 机制,下面详细介绍。

3.2. Session(服务端存储 + Cookie关联)

原理

服务器在内存/数据库存储会话数据,通过Cookie传递唯一Session ID绑定用户。

示例流程

  • 用户登录
    • 服务端生成Session ID(如abc123),存储数据(如{user_id: 100, username: "Alice"}),并通过Cookie返回ID。
  • 后续请求
    • 浏览器携带Session ID,服务端查询对应数据。

Session 机制存在的问题:

采用 Session 机制时,Session 信息保存于服务端,而服务端一般会采用负载均衡代理的多个服务器,第一次会话可能打到了web01,然后会话信息存放到了web01上;第二次负载均衡将请求转发到了web02,便无法读取该 Session 信息了。

解决方法就是将会话信息存放到一个后端服务器共享的地方(如数据库),一般采用 redis 来储存 Session 信息效率更高。但为了防止单点故障,就需要引入 redis 集群,随着规模的发展这个集群可能会成为性能瓶颈。

所有后面又引入了下面的方案。

3.3. Token(无状态方案)

原理

服务端不存储会话数据,通过签名Token(如JWT)验证客户端身份。

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络间安全传输声明(Claims)的轻量级令牌。它通过数字签名或加密确保数据的完整性和可信性,常用于身份验证(如替代 Session-Cookie 机制)和信息交换。

JWT 原理

JWT 由三部分组成,用 . 分隔,格式为:Header.Payload.Signature

  • Header(头部)
    • 声明令牌类型(typ: "JWT")和签名算法(如 alg: "HS256" 或 RS256)。
    • 示例:
{
  "alg": "HS256",
  "typ": "JWT"
}


# 上面的 JSON 最终会被 Base64Url 编码成一个字符串(假设为 xxxxxx)。
Bash
  • Payload(状态信息)
    • 示例:
{
  "sub": "1234567890",   # 过期时间
  "name": "John Doe",
  "admin": true
}


# 上面的 JSON 最终会被 Base64Url 编码成一个字符串(假设为 yyyyyy)。
Bash
  • Signature(签名)
    • 对 Header 和 Payload 的签名,防止篡改。
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret_key
)


# 得到的是"header+payload+盐/密钥"三者通过头里存放得 hash 算法计算出来得 hash 值(假设为 zzzzzz)。
Bash

最后得到的 JWT 为 xxxxxx.yyyyyy.zzzzzz。

JWT 工作流程(以身份验证为例):

  1. 用户首次登录时,服务器验证用户的凭证(如用户名和密码)。如果凭证有效,服务器则生成一个 JWT,并将其发送回客户端。
  2. 客户端应用程序(如使用Vue.js、React等编写的前端代码)收到 JWT 后,会将其存储在本地存储(最常用的是 localStorage,有时也会使用 sessionStorage)中。这样做是为了持久化用户会话,即使在浏览器关闭后再重新打开时,用户仍然保持登录状态。
  3. 当客户端应用需要向服务器发送需要认证的请求时,它会从本地存储中检索 JWT,并将其作为Authorization头的一部分附加到请求中。通常,它是以 Bearer 标记形式发送的,如 Authorization: Bearer 。
  4. 服务器在接收到请求时,会解析 Authorization 头,验证 JWT 的有效性(如检 查签名、是否过期等)。如果验证通过,则允许请求继续进行。如果失败,可能会返回错误响应,如 401 Unauthorized。

4. HTTP 协议加密

HTTPS(HTTP + SSL/TLS):HTTPS在HTTP基础上加入SSL/TLS加密层,默认端口443。

4.1. SSL 详解

下面先了解一些相关知识点。

4.1.1. 对称加密与非对称加密

对称加密 (Symmetric Encryption)

  • 单一密钥:加密和解密使用相同的密钥。
  • 高效快速:计算复杂度低,适合大数据量加密。
  • 密钥分发问题:如何安全地共享密钥是主要挑战。

非对称加密 (Asymmetric Encryption):

  • 密钥对:公钥(公开)和私钥(保密),公钥加密私钥解密。
  • 计算复杂:比对称加密慢1000倍以上,不适合大数据量加密。

4.1.2. SSL 加密通信流程

SSL 加密则是使用了对称加密与非对称加密的结合,在握手阶段采用非对称加密,通信阶段采用对称加密,兼顾了安全与效率。下面详细介绍 SSL 加密通信流程:

单向认证:

  • 握手阶段
    • 客户端发起握手,发送:
      • 支持的 SSL 版本
      • 支持的加密套件列表,如:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256等。
    • 服务器响应:
      • 选择的 SSL 版本
      • 选择的加密套件(此时的加密方案是明文传输,还是有一定的风险,对与安全要求高的场景可以选择双向认证)
      • 服务器数字证书(包含公钥)
    • 证书验证
      • 客户端验证:
        • 证书是否由受信任CA签发
        • 证书是否在有效期内
        • 证书中的域名是否匹配
        • 证书是否被吊销(CRL/OCSP检查)
    • 密钥交换
      • 验证通过后,客户端使用服务端选择的加密方式生成密钥(用于通信时对称加密)。
      • 将生成的密钥用服务端公钥加密后发送到服务端。
      • 服务端收到客户端返回的加密信息后,使用自己的私钥进行解密,获得对称加密密钥。
    • 加密通信阶段
      • 在接下来的会话中,服务端和客户端将会使用对称加密, 保证通信过程中信息的安全。

双向认证:

  • 握手阶段
    • 客户端发起握手,发送:
      • 支持的 SSL 版本
      • 支持的加密套件列表,如:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256等。
    • 服务器响应:
      • 请求客户端证书和公钥。
    • 证书验证
      • 客户端验证:
        • 证书是否由受信任CA签发
        • 证书是否在有效期内
        • 证书中的域名是否匹配
        • 证书是否被吊销(CRL/OCSP检查)
      • 服务端验证:
        • 当服务端向客户端请求了证书时客户端将证书和公钥发送到服务端。
        • 服务端对证书进行验证。
    • 密钥交换
      • 服务端验证通过后,服务端将选择的 SSL 版本和加密套件使用客户端公钥进行加密并发送给客户端。(此时加密方案不是采用明文的方式发送的,对比单向认证更安全)。
      • 客户端使用服务端选择的加密方式生成密钥(用于通信时对称加密)。
      • 将生成的密钥用服务端公钥加密后发送到服务端。
      • 服务端收到客户端返回的加密信息后,使用自己的私钥进行解密,获得对称加密密钥。
  • 加密通信阶段
    • 在接下来的会话中,服务端和客户端将会使用对称加密, 保证通信过程中信息的安全。

4.2. TLS

TLS(Transport Layer Security)是更为安全的升级版 SSL。由于
SSL 这一术语更为常用,所以我们通常仍将 TLS 证书称作 SSL 证书。

总结概括:

  • SSL 是一种早期的加密协议,1999年前后随着互联网的快速发展互联网工程任务组(IETF)对 SSL 进行了标准化,并改名为 TLS,尽管协议名称发生了 变化,但核心概念保持不变。
  • TLS 基于 SSL3.0,进行了改进和升级解决了 SSL 的一些安全漏洞,相比 SSL 更加安全高效。换句话说,TLS 是 SSL 的更安全高效的版本。SSL 已基本被 TLS 取代,当前最新的协议版本是 TLS1.3。统计显示:截至2023年,全球95%的HTTPS流量已使用TLS 1.2或1.3,仅0.3%仍使用SSL协议。

5. 自签 CA 证书步骤

准备工作

确保已安装OpenSSL(Linux/macOS通常内置,Windows需下载)。

生成自签CA根证书

(1) 生成CA私钥

openssl genrsa -out ca.key 4096  # 推荐RSA 4096位,或ECDSA:openssl ecparam -genkey -name secp384r1 -out ca.key
Bash

(2) 创建CA证书(自签)

openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt -subj "/CN=My Root CA/O=My Org/C=US"

# 参数说明
# -x509:生成自签名证书。
# -days 3650:有效期10年(按需调整)。
# -subj:证书主题(可省略,交互式填写)。
Bash

用CA签发服务器证书

(1) 生成服务器私钥

openssl genrsa -out server.key 2048
Bash

(2) 创建证书签名请求(CSR)

openssl req -new -key server.key -out server.csr -subj "/CN=example.com/O=My Server"

# 交互式填写:若省略-subj,会提示输入国家、域名等信息。
Bash

(3) 用CA签发服务器证书

创建扩展配置文件server.ext

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage=digitalSignature,keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName=DNS:example.com,DNS:*.example.com  # 多域名/通配符支持
Bash

签发证书:

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext
Bash

部署与信任

(1) 服务器配置

server.crtserver.key部署到Web服务器(如Nginx):

ssl_certificate     /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
Bash

(2) 客户端信任CA

Windows:双击ca.crt → “安装证书” → 选择“受信任的根证书颁发机构”。

Linux/macOS

# macOS
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca.crt

# Linux (Debian/Ubuntu)
sudo cp ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
Bash
上一篇
下一篇