Django REST Framework Simple JWT 访问令牌与刷新令牌实践指南
Django REST Framework Simple JWT 访问令牌与刷新令牌实践指南
一、概述
djangorestframework-simplejwt是 Django REST Framework (DRF) 的 JWT 认证扩展库,通过访问令牌 (Access Token)和刷新令牌 (Refresh Token)实现无状态、高安全性的用户认证。本文详细解析两类令牌的核心机制、安全配置及最佳实践,帮助开发者在实际项目中正确使用。
二、核心概念:访问令牌与刷新令牌
2.1 访问令牌(Access Token)
作用
- 短期凭证:用于直接访问受保护的 API 端点(如用户信息、支付接口)。
- 身份验证:服务器通过验证令牌签名确认用户身份,无需查询数据库。
- 时效性短:默认有效期 5 分钟(可配置为 5-15 分钟),降低泄露风险。
- 无状态性:包含用户信息(如 ID、角色)在 JWT Payload 中,服务端仅验证签名。
- 传输方式:通过 HTTP 请求头传递:Authorization: Bearer <access_token>
特点
生成流程
用户登录时,服务器验证用户名/密码后生成访问令牌。示例负载(Payload):
{
"token_type": "access", // 令牌类型
"exp": 1714675200, // 过期时间戳(2024-05-03 00:00:00)
"iat": 1714674900, // 签发时间戳(2024-05-02 23:55:00)
"jti": "a1b2c3d4-5678-90ef-ghij-klmnopqrstuv", // 唯一标识(防重放攻击)
"user_id": 42, // 用户 ID(关键标识)
"username": "john_doe", // 用户名(可选自定义字段)
"role": "editor" // 自定义声明(如用户角色)
}
2.2 刷新令牌(Refresh Token)
作用
- 令牌续签:当访问令牌过期时,使用刷新令牌获取新的访问令牌,避免用户重复登录。
- 长期会话管理:默认有效期 1 天(可配置为 1-30 天),平衡安全性与用户体验。
- 不直接访问资源:仅用于调用/token/refresh/接口获取新令牌。
- 安全存储:需客户端安全存储(如HttpOnly Cookie、设备安全存储),防止泄露。
- 可选轮换机制:启用ROTATE_REFRESH_TOKENS后,每次刷新生成新刷新令牌,旧令牌失效。
特点
刷新流程
1. 客户端发送刷新请求:POST /api/token/refresh/
Content-Type: application/json
{
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcxNDc2MTYwMCwiaWF0IjoxNzE0Njc1MjAwLCJqdGkiOiJiM2U0ZjU2Ny04OTBqLTExZTktYjViNS0wMjQyYWMxMzBlZjQiLCJ1c2VyX2lkIjo0Mn0.abc123xyz"
}
2. 服务器验证刷新令牌有效性,返回新令牌(若启用轮换,包含新刷新令牌):{
"access": "new_access_token_here",
"refresh": "new_refresh_token_here" // 仅当 ROTATE_REFRESH_TOKENS=True 时返回
}
三、核心安全机制与配置
3.1 令牌有效期控制
通过SIMPLE_JWT配置调整令牌生命周期,平衡安全性与用户体验。
|
令牌类型 |
默认有效期 |
配置参数 |
推荐范围 |
|
访问令牌 |
5 分钟 |
ACCESS_TOKEN_LIFETIME |
5-15 分钟 |
|
刷新令牌 |
1 天 |
REFRESH_TOKEN_LIFETIME |
1-7 天(敏感系统更短) |
示例配置(settings.py):
from datetime import timedelta
SIMPLE_JWT = {
# 调整有效期
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=15), # 访问令牌 15 分钟过期
"REFRESH_TOKEN_LIFETIME": timedelta(days=3), # 刷新令牌 3 天过期
}
3.2 防止令牌滥用
黑名单机制(Blacklisting)
启用后,旧刷新令牌在轮换后加入黑名单,防止重复使用。需安装djangorestframework-simplejwt-token-blacklist应用。
配置:
SIMPLE_JWT = {
"ROTATE_REFRESH_TOKENS": True, # 每次刷新生成新刷新令牌
"BLACKLIST_AFTER_ROTATION": True, # 旧刷新令牌加入黑名单
"BLACKLIST_TOKEN_CHECKS": [
"rest_framework_simplejwt.token_blacklist.blacklist.check_blacklisted" # 黑名单检查函数
],
}
签名验证
通过加密算法(如HS256或RS256)确保令牌未被篡改:
- 对称加密(HS256):使用同一密钥签名和验证(适合单服务场景)。
- 非对称加密(RS256):私钥签名、公钥验证(适合多服务/跨域场景)。
配置示例(HS256):
SIMPLE_JWT = {
"ALGORITHM": "HS256", # 加密算法
"SIGNING_KEY": os.getenv("JWT_SECRET_KEY"), # 从环境变量获取密钥(64+字符随机字符串)
"VERIFYING_KEY": None, # 对称加密无需公钥
}
四、完整认证流程
sequenceDiagram
participant Client
participant Server
Client->>Server: 发送登录请求(用户名/密码)
Server->>Client: 返回 access_token + refresh_token
loop 访问受保护资源
Client->>Server: 发送 API 请求(携带 access_token)
Server->>Client: 返回资源数据
end
alt access_token 过期
Client->>Server: 发送刷新请求(携带 refresh_token)
Server->>Client: 返回新 access_token(+ 新 refresh_token)
end
五、最佳实践
5.1 客户端存储策略
- 访问令牌:存储在内存或sessionStorage(浏览器关闭即失效),避免localStorage(防 XSS 攻击)。
- 刷新令牌:使用HttpOnly + Secure Cookie存储(防 XSS 和中间人攻击),或设备级安全存储(如 iOS Keychain、Android Keystore)。
5.2 自定义令牌负载
通过继承TokenObtainPairSerializer添加用户自定义信息(如邮箱、角色)到令牌中。
示例代码:
# serializers.py
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import RefreshToken
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
"""添加自定义声明到令牌"""
token = super().get_token(user)
# 自定义字段(根据用户模型添加)
token["email"] = user.email
token["role"] = user.role # 假设用户模型有 role 字段
token["is_staff"] = user.is_staff
return token
5.3 敏感操作增强
对支付、删除账户等敏感操作,使用短有效期访问令牌(如 5 分钟),降低泄露风险。
配置:
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=5), # 敏感操作缩短为 5 分钟
}
六、常见问题与解决方案
Q1: 刷新令牌泄露怎么办?
- 立即失效:通过黑名单机制将泄露的刷新令牌加入黑名单(需启用BLACKLIST_AFTER_ROTATION)。
- 缩短有效期:将REFRESH_TOKEN_LIFETIME设为更短(如 1 天),减少攻击窗口。
- 客户端:删除本地存储的访问令牌和刷新令牌。
- 服务端:将用户的所有有效刷新令牌加入黑名单(需自定义逻辑遍历并标记)。
- 最小化攻击窗口:即使令牌被截获,攻击者仅有几分钟时间滥用。
- 无状态补偿:JWT 无法实时失效(如用户退出登录),短有效期是弥补无状态缺陷的关键措施。
Q2: 如何主动注销用户?
Q3: 为何访问令牌有效期要短?
七、总结
djangorestframework-simplejwt通过访问令牌与刷新令牌的协同工作,为 DRF API 提供了安全、高效的认证方案。核心实践包括:
- 短有效期访问令牌降低泄露风险;
- 刷新令牌结合轮换与黑名单机制管理长期会话;
- 自定义负载和安全存储策略增强灵活性与安全性。
通过合理配置和最佳实践,开发者可在用户体验与系统安全间取得平衡,构建符合企业级标准的认证体系。
浙公网安备 33010602011771号