RFC 7235 - HTTP/1.1: 认证 (Authentication)
文档信息
- RFC编号: 7235
- 标题: Hypertext Transfer Protocol (HTTP/1.1): Authentication
- 标题(中文): 超文本传输协议(HTTP/1.1): 认证
- 发布日期: 2014年6月
- 作者: R. Fielding (Adobe), J. Reschke (greenbytes)
- 废弃文档: RFC 2616, RFC 2617 (部分)
- 状态: 标准轨道 (Standards Track)
摘要
HTTP提供了简单的质询-响应认证框架,服务器可以质询客户端请求,客户端可以提供认证信息。本文档定义了HTTP认证框架的通用机制,包括401、407状态码以及相关的头部字段。
核心概念
HTTP认证流程
1. 客户端请求受保护资源
→ GET /admin HTTP/1.1
2. 服务器返回质询
← HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Admin Area"
3. 客户端提供凭证
→ GET /admin HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==
4. 服务器验证并响应
← HTTP/1.1 200 OK
[受保护的内容...]
认证方案 (Authentication Schemes)
HTTP支持多种认证方案:
- Basic: 基本认证(RFC 7617)
- Bearer: Bearer令牌(RFC 6750)
- Digest: 摘要认证(RFC 7616)
- OAuth: OAuth认证(RFC 6749)
401 Unauthorized
表示请求缺少有效的认证凭证。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="WallyWorld"
Content-Type: text/html
Content-Length: 0
重要: 401的名称"Unauthorized"实际上是**未认证(Unauthenticated)**的意思。
407 Proxy Authentication Required
表示客户端必须先通过代理进行认证。
HTTP/1.1 407 Proxy Authentication Required
Proxy-Authenticate: Basic realm="Proxy Access"
WWW-Authenticate头部
服务器使用此头部定义认证质询。
基本语法
WWW-Authenticate: <scheme> realm="<realm>" [, <param>=<value>]*
示例
单个质询:
WWW-Authenticate: Basic realm="Admin Area"
多个质询(客户端可以选择):
WWW-Authenticate: Bearer realm="API", Basic realm="API"
带额外参数:
WWW-Authenticate: Digest
realm="[email protected]",
qop="auth,auth-int",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
realm参数
**realm(领域)**定义了保护空间的范围:
WWW-Authenticate: Basic realm="管理员区域"
- 通常显示在浏览器的认证对话框中
- 帮助用户理解需要什么凭证
- 相同realm的资源共享凭证
Authorization头部
客户端使用此头部提供认证凭证。
基本语法
Authorization: <scheme> <credentials>
示例
Basic认证:
Authorization: Basic dXNlcjpwYXNzd29yZA==
Bearer令牌:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Digest认证:
Authorization: Digest username="user",
realm="[email protected]",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
uri="/dir/index.html",
response="6629fae49393a05397450978507c4ef1"
Proxy-Authenticate和Proxy-Authorization
用于代理认证,工作方式类似于WWW-Authenticate和Authorization。
代理认证流程
1. 客户端请求
→ GET http://example.com/ HTTP/1.1
2. 代理要求认证
← HTTP/1.1 407 Proxy Authentication Required
Proxy-Authenticate: Basic realm="Proxy"
3. 客户端提供凭证
→ GET http://example.com/ HTTP/1.1
Proxy-Authorization: Basic cHJveHk6cGFzc3dvcmQ=
4. 代理转发请求
[代理] → GET / HTTP/1.1
Host: example.com
Basic认证 (RFC 7617)
最简单但不安全的认证方案。
编码凭证
// 1. 组合用户名和密码
const credentials = "username:password";
// 2. Base64编码
const encoded = btoa(credentials);
// 结果: "dXNlcm5hbWU6cGFzc3dvcmQ="
// 3. 构造Authorization头部
const auth = `Basic ${encoded}`;
完整示例
GET /admin HTTP/1.1
Host: example.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
安全警告
危险: Basic认证以Base64编码传输凭证,不是加密!
dXNlcm5hbWU6cGFzc3dvcmQ=
↓ Base64解码
username:password
必须使用HTTPS:
✗ http://example.com + Basic认证 = 明文传输
✓ https://example.com + Basic认证 = 加密传输
Bearer令牌认证 (RFC 6750)
现代Web API常用的认证方案。
使用场景
通常与OAuth 2.0一起使用:
1. 用户登录,获取访问令牌
← { "access_token": "eyJhbG...", "token_type": "Bearer" }
2. 使用令牌访问API
→ GET /api/user HTTP/1.1
Authorization: Bearer eyJhbG...
示例
GET /api/resource HTTP/1.1
Host: api.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
错误响应
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="API",
error="invalid_token",
error_description="The access token expired"
Digest认证 (RFC 7616)
比Basic更安全,但更复杂。
特点
- 不直接传输密码
- 使用质询-响应机制
- 防止重放攻击(通过nonce)
简化流程
1. 服务器发送质询(包含nonce)
← WWW-Authenticate: Digest realm="...", nonce="..."
2. 客户端计算响应
response = MD5(
MD5(username:realm:password) :
nonce :
MD5(method:uri)
)
3. 客户端发送响应
→ Authorization: Digest username="...", response="..."
实际应用场景
场景1: Web应用登录
传统表单 + Session(推荐):
POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=user&password=pass
→ HTTP/1.1 302 Found
Set-Cookie: sessionid=abc123; HttpOnly; Secure
不使用HTTP Basic认证(除非通过HTTPS)。
场景2: API认证
Bearer Token(推荐):
GET /api/users HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
场景3: 管理界面保护
Basic认证 + HTTPS(简单场景):
GET /admin HTTP/1.1
Host: secure.example.com
Authorization: Basic YWRtaW46c2VjcmV0
场景4: 微服务间认证
相互TLS + Bearer Token:
GET /internal/service HTTP/1.1
Host: internal.example.com
Authorization: Bearer service-token-123
认证与授权
区别
认证 (Authentication): "你是谁?"
Authorization: Bearer [身份令牌]
授权 (Authorization): "你能做什么?"
令牌包含的权限:
{
"user_id": "123",
"roles": ["admin", "editor"],
"permissions": ["read", "write", "delete"]
}
HTTP状态码
- 401 Unauthorized: 认证失败或缺少认证
- 403 Forbidden: 认证成功,但没有权限
用户A尝试访问管理员资源:
→ 未登录 → 401 Unauthorized
→ 已登录(普通用户)→ 403 Forbidden
→ 已登录(管理员)→ 200 OK
最佳实践
服务器端
-
始终使用HTTPS
✓ https://api.example.com
✗ http://api.example.com -
提供清晰的realm
WWW-Authenticate: Bearer realm="My API v1" -
支持多种认证方案
WWW-Authenticate: Bearer realm="API", Basic realm="API" -
限制失败尝试
- 实施速率限制
- 记录失败的认证尝试
- 考虑临时锁定账户
-
安全存储凭证
- 密码使用强哈希(bcrypt, Argon2)
- 令牌使用安全随机生成器
客户端端
-
安全存储令牌
// ✓ 推荐
sessionStorage.setItem('token', token);
// ✗ 避免(XSS风险)
localStorage.setItem('token', token); -
处理401响应
if (response.status === 401) {
// 清除本地令牌
// 重定向到登录页
} -
令牌刷新
// 在令牌过期前自动刷新
if (tokenExpiresIn < 5 * 60) {
refreshToken();
}
安全考虑
1. 中间人攻击
风险: 未加密传输凭证
防御: 使用HTTPS
✗ HTTP + Basic: 明文凭证被窃取
✓ HTTPS + Basic: 加密传输,安全
2. 重放攻击
风险: 攻击者截获并重放认证请求
防御:
- 使用短期令牌
- 实施nonce机制
- 绑定令牌到特定客户端
3. 凭证泄露
风险: 凭证被记录或泄露
防御:
- 不在URL中传递凭证
- 使用短期访问令牌
- 实施刷新令牌机制
✗ https://api.example.com/data?token=abc123
✓ Authorization: Bearer abc123
4. XSS攻击
风险: 恶意脚本窃取令牌
防御:
- 使用HttpOnly Cookie
- 实施CSP策略
- 验证和清理输入
总结
HTTP认证提供了灵活的框架:
- 信: 准确实现认证协议,确保安全性
- 达: 清晰表达认证要求,便于客户端实现
- 雅: 优雅设计认证流程,提升用户体验
核心原则:
- 始终使用HTTPS
- 选择适合场景的认证方案
- 实施纵深防御策略
- 定期轮换凭证
现代推荐:
- Web应用: OAuth 2.0 + OpenID Connect
- API: Bearer Token (JWT)
- 简单场景: Basic + HTTPS
- 避免: Digest (过时且复杂)
相关文档:
- RFC 7617: Basic认证
- RFC 7616: Digest认证
- RFC 6750: Bearer Token
- RFC 6749: OAuth 2.0