You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST Framework自定义用户模型下JWT令牌失效问题排查

DRF自定义User模型下JWT令牌验证失败排查方案

问题场景

已基于Django REST Framework实现JWT登录功能,使用自定义User模型,依赖库、settings.py配置均已完成,登录接口可正常返回access和refresh令牌,但用access令牌以Bearer方式在Postman访问带IsAuthenticated权限的BalanceAPI时,始终返回令牌无效/过期错误。

依赖与环境版本

  • Python 3.11.6
  • asgiref 3.7.2
  • Django 5.0
  • django-debug-toolbar 4.2.0
  • djangorestframework 3.14.0
  • djangorestframework-simplejwt 5.3.1
  • PyJWT 2.8.0

错误响应

{
    "detail": "Given token not valid for any token type",
    "code": "token_not_valid",
    "messages": [
        {
            "token_class": "AccessToken",
            "token_type": "access",
            "message": "Token is invalid or expired"
        }
    ]
}

排查与解决步骤

1. 适配自定义User模型的JWT配置

确保自定义User模型继承自AbstractUser或AbstractBaseUser,且settings.py中指定正确的用户模型与JWT关联字段:

# settings.py
AUTH_USER_MODEL = 'your_app.YourCustomUser'

SIMPLE_JWT = {
    'USER_ID_FIELD': 'id',  # 对应自定义User模型的主键字段,若用其他主键需修改
    'USER_ID_CLAIM': 'user_id',
}

同时确认模型已实现__str__方法,避免令牌生成时出现序列化异常。

2. 校验令牌签名与密钥一致性

检查settings.py中的SECRET_KEY是否在令牌生成和验证时完全一致,避免开发/测试环境密钥不匹配。simplejwt默认使用Django的SECRET_KEY签名,不要随意覆盖SIGNING_KEY配置,除非明确使用自定义密钥:

# 错误示例:若未确认自定义密钥,请勿添加该行
# SIMPLE_JWT = {'SIGNING_KEY': 'your_custom_key'}

3. 规范请求头格式

Postman中请求头必须严格遵循格式:

  • 键:Authorization
  • 值:Bearer <你的access令牌>
    注意Bearer与令牌之间有一个空格,避免小写拼写或多余空格导致验证失败。

4. 同步时间与校验令牌有效期

检查令牌有效期配置,确保测试时access令牌未过期:

# settings.py
from datetime import timedelta

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),  # 默认5分钟,可临时延长用于测试
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
}

同时确认服务器与本地设备的系统时间一致,时间差过大可能导致令牌被判定为过期。

5. 配置DRF认证类

确保settings.py中DRF默认认证类包含JWT认证:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        # 其他认证类按需保留
    ],
}

若BalanceAPI视图单独指定了认证类,需确保包含JWTAuthentication:

from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.permissions import IsAuthenticated

class BalanceAPI(APIView):
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    # 视图逻辑

6. 手动解码验证令牌

在Django Shell中解码令牌,定位具体错误:

import jwt
from django.conf import settings

token = "你的access令牌"
try:
    payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
    print(payload)
except jwt.ExpiredSignatureError:
    print("令牌已过期")
except jwt.InvalidTokenError as e:
    print(f"令牌无效: {e}")

根据解码结果排查签名错误、字段缺失等问题。


内容的提问来源于stack exchange,提问作者dj-Yang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 02:23:21