JWT工作原理与实战应用
JWT(JSON Web Token)是一种基于JSON的开放标准(RFC 7519),用于在各方之间安全传递声明。它特别适用于分布式系统中的单点登录场景,能够高效地在身份认证方与服务提供方之间传递用户身份信息,并支持自定义业务数据。
传统Session机制依赖服务端存储会话状态,带来高负载压力。而JWT将关键信息封装在客户端持有的令牌中,服务端无需保存状态,显著降低存储开销。
JWT结构组成
一个完整的JWT由三部分通过英文句点连接而成:
- 头部(Header):描述令牌类型及签名算法,例如
{"alg": "HS256", "typ": "JWT"}。 - 载荷(Payload):包含实际数据,如用户标识、过期时间、签发时间等。可自定义字段。
- 签名(Signature):使用密钥对前两部分进行加密生成,确保内容完整性。
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Base64编码机制
Base64是一种二进制到文本的编码方式,结果长度为4的倍数(不足用=补全)。常用于网络传输中将二进制数据转为可读字符串。
import base64
import json
# 编码
data = {'user_id': 1, 'exp': 1640995200}
encoded_data = base64.b64encode(json.dumps(data).encode('utf-8'))
print(encoded_data.decode())
# 解码
decoded = base64.b64decode('...').decode()
print(decoded)
该编码不提供安全性,仅用于格式转换,适合图片、文件等资源的嵌入式传输。
认证流程详解
1. 登录阶段
客户端提交用户名和密码至登录接口,服务端验证成功后:
- 构造载荷(含用户信息、过期时间等)
- 使用密钥和指定算法(如HS256)生成签名
- 返回完整JWT令牌给客户端,由前端保存(如本地存储或内存)
2. 后续请求阶段
客户端在访问受保护接口时,在请求头中携带JWT:
Authorization: Bearer <token_value>
服务端收到请求后:
- 提取Token并解码头部与载荷
- 使用相同密钥重新计算签名
- 比较计算结果与原始签名是否一致
- 若一致且未过期,则认证通过,允许访问资源
Django REST Framework 中集成 JWT
在Django + DRF项目中,常用JWT实现方案包括:
djangorestframework-jwt:成熟但已不再维护djangorestframework-simplejwt:推荐使用,更新频繁,配置简洁
使用 simplejwt 实现登录
安装模块:
pip install djangorestframework-simplejwt
配置设置项:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': True,
}
定义登录路由:
from rest_framework_simplejwt.views import TokenObtainPairView
from django.urls import path
urlpatterns = [
path('auth/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
]
此视图会返回一对令牌:访问令牌(access token)和刷新令牌(refresh token)。
自定义响应格式
可通过重写序列化器定制返回数据:
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
# 添加自定义字段
token['username'] = user.username
token['email'] = user.email
return token
注册使用:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}
SIMPLE_JWT = {
'TOKEN_OBTAIN_SERIALIZER': 'myapp.serializers.CustomTokenObtainPairSerializer',
}
权限控制配置
配合权限类实现登录态校验:
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import api_view, permission_classes
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def protected_view(request):
return Response({'message': '只有登录用户才能访问'})
核心源码逻辑解析
以 simplejwt 为例,其核心流程如下:
TokenObtainPairView接收登录请求,调用TokenObtainPairSerializer验证凭据- 成功后通过
get_token()方法构建JWT载荷 - 调用
jwt.encode()生成最终令牌 - 响应中返回
access和refresh令牌
验证过程则由 JWTAuthentication 类完成:
- 从请求头提取
Authorization: Bearer <token>中的token值 - 调用
jwt.decode()解析并验证签名、过期时间等 - 若有效,返回用户对象;否则抛出异常
整个过程无状态、可扩展,适合微服务架构。