直接使用djangorestframework-simplejwt可实现无状态jwt认证,但必须正确配置installed_apps、rest_framework.default_authentication_classes和simple_jwt字典,否则请求静默401;需注意auth_header_types格式、access_token_lifetime类型、user_id_field匹配及自定义tokenobtainpairserializer扩展载荷。

直接用 djangorestframework-simplejwt 就能跑通无状态 JWT 认证,不用自己手写签发/校验逻辑,但配置错一个地方——比如 AUTH_HEADER_TYPES 拼错、SIMPLE_JWT 字典没嵌套对、或漏加 rest_framework_simplejwt 到 INSTALLED_APPS——请求就静默 401,连日志都不报错。
pip install 后必须加进 INSTALLED_APPS 才生效
djangorestframework-simplejwt 不是纯工具库,它带认证类、视图、信号和数据库迁移(比如启用黑名单时)。如果只 pip install 却没在 INSTALLED_APPS 里注册,JWTAuthentication 类根本不会被 Django 加载,后续所有配置都白搭。
必须确保:
-
'rest_framework'和'rest_framework_simplejwt'都在INSTALLED_APPS列表中 - 如果要用令牌黑名单(如登出),还得加上
'rest_framework_simplejwt.token_blacklist' - 顺序无关,但少任何一个,
manage.py migrate可能报找不到 app 的错
REST_FRAMEWORK.DEFAULT_AUTHENTICATION_CLASSES 必须显式指定
Django REST Framework 默认不启用任何认证。即使装了 simplejwt,不把它写进 DEFAULT_AUTHENTICATION_CLASSES,所有 IsAuthenticated 权限检查都会直接放行(开发环境容易误以为“认证成功”)。
正确写法是:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
注意点:
- 别漏掉末尾的逗号(尤其在单元素列表里,Python 容忍但易出错)
-
JWTAuthentication类路径要完整,大小写不能错 - 如果还保留
SessionAuthentication,记得把它移走,否则浏览器访问 API 会意外走 session 分支,掩盖 JWT 问题
SIMPLE_JWT 配置项位置和常见填坑点
SIMPLE_JWT 是个顶层字典,必须和 INSTALLED_APPS、REST_FRAMEWORK 并列写在 settings.py 里,不能塞进 REST_FRAMEWORK 里面。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
最常踩的坑:
-
'ACCESS_TOKEN_LIFETIME'必须是timedelta实例,不是整数分钟数:写timedelta(minutes=5),别写5 -
'AUTH_HEADER_TYPES'默认是('Bearer',),但前端 Axios 或 Fetch 发请求时如果写成Authorization: Bearer xxx少了个空格,或写成token xxx,就会 401 —— 建议先用 curl 测试:curl -H "Authorization: Bearer <token>" http://localhost:8000/api/test/</token> -
'USER_ID_FIELD'如果你用的是自定义用户模型且主键不是id(比如叫uuid),这里必须同步改成'uuid',否则 token 解析时取不到用户
TokenObtainPairView 返回的字段不够用?重写序列化器
默认 TokenObtainPairView 只返回 access 和 refresh 两个字段。如果前端需要立刻拿到用户名、头像、角色等,不能靠额外查一次用户接口——那违背了 JWT “载荷自带信息” 的设计初衷。
做法是继承 TokenObtainPairSerializer:
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from myapp.models import User
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['username'] = user.username
token['email'] = user.email
token['is_staff'] = user.is_staff
return token
然后在 urls.py 中替换默认视图:
from .serializers import CustomTokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer
这样返回的 JSON 就会多出你加的字段,且无需额外 DB 查询。
真正麻烦的从来不是生成 token,而是让每个环节都严格对齐:前端传的 header 格式、后端解析的 claim 名、用户模型字段名、过期时间单位、甚至 settings.py 里那个缩进多了一格的 SIMPLE_JWT 字典——错一个,整个链路就断在看不见的地方。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










