Django中过期Access Token被ModelViewSet接受的问题求助
问题分析与解决方案
首先明确一点:JWT Access Token过期时,标准响应应该是401 Unauthorized(认证失败),而非403 Forbidden(权限不足)。你的ModelViewSet在token过期后仍返回数据,说明认证环节没有正确执行,先排查以下几点:
1. 检查请求头格式是否正确
你提到请求头设置为Authentication = 'Bearer ${access_token}',这里是关键错误:simplejwt默认读取的请求头是Authorization,而非Authentication。如果请求头名称错误,JWTAuthentication无法识别token,此时若你的视图没有正确拦截匿名用户(但你设置了IsAuthenticated),理论上应该返回403,但实际返回数据可能是测试时的缓存或其他异常情况。
正确的请求头格式应为:
Authorization: Bearer <你的过期access_token>
2. 确认simplejwt的认证逻辑正常工作
simplejwt的JWTAuthentication类本身会自动校验token的过期时间(exp声明),无需自定义认证类。如果token确实过期,它会抛出TokenError异常,DRF会自动转换为401响应。
如果确认请求头正确但仍有问题,可检查以下配置:
- 确保
SIMPLE_JWT中的LEEWAY设置为0(你已经设置了),这个参数是允许的时间误差,避免因服务器时间差导致误判。 - 检查simplejwt版本,建议升级到最新稳定版,避免旧版本的bug。
3. 强制返回403(若确有需求)
如果你因业务需求必须返回403而非标准的401,可以通过自定义异常处理或认证类实现:
方式一:自定义异常处理
在项目的settings.py中配置DRF的异常处理器:
from rest_framework.views import exception_handler from rest_framework_simplejwt.exceptions import TokenError from rest_framework.response import Response def custom_exception_handler(exc, context): # 捕获simplejwt的TokenError(包括过期、无效等) if isinstance(exc, TokenError): return Response( {"detail": exc.args[0], "code": "token_not_valid"}, status=403 ) # 调用默认异常处理器处理其他情况 response = exception_handler(exc, context) return response REST_FRAMEWORK = { # ... 其他配置 'EXCEPTION_HANDLER': 'your_project_name.settings.custom_exception_handler', }
方式二:自定义认证类(可选)
如果需要更精细的控制,可以继承JWTAuthentication并重写认证方法:
from rest_framework_simplejwt.authentication import JWTAuthentication from rest_framework_simplejwt.exceptions import TokenError from rest_framework.exceptions import PermissionDenied class CustomJWTAuthentication(JWTAuthentication): def authenticate(self, request): try: return super().authenticate(request) except TokenError as e: raise PermissionDenied(detail=str(e), code="token_not_valid")
然后在settings.py中替换默认的认证类:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'your_app_name.authentication.CustomJWTAuthentication', ) }
总结
- 优先排查请求头格式问题,这是最常见的错误原因;
- 无需自定义认证类即可处理token过期,simplejwt默认逻辑已覆盖;
- 若需返回403,通过自定义异常处理器或认证类实现即可。
内容的提问来源于stack exchange,提问作者NeX'T'iME
相关产品推荐
相关产品推荐

