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

Django搭配REST框架、SimpleJWT时自定义中间件user始终为匿名如何解决

问题原因

  • Django自带的AuthenticationMiddleware仅会处理session认证场景下的用户身份填充,而rest_framework_simplejwt的JWT token校验逻辑属于DRF框架的视图层逻辑,默认会在请求匹配到路由、进入对应视图之前才执行,中间件执行时该校验还未触发,因此request.user始终是未认证的匿名用户。
  • 若自定义中间件放在了AuthenticationMiddleware之前,连session场景下的已认证用户也无法识别,同样会触发该问题。

解决方案

方案1:改用DRF自定义认证类实现(推荐)

该方案贴合DRF的请求生命周期,无额外重复校验开销,直接继承SimpleJWT的JWTAuthentication类,在认证成功后更新字段即可:

from rest_framework_simplejwt.authentication import JWTAuthentication
from django.utils.timezone import now

class UpdateLastRequestJWTAuthentication(JWTAuthentication):
    def authenticate(self, request):
        auth_result = super().authenticate(request)
        # 仅认证成功时更新字段
        if auth_result is not None:
            user, validated_token = auth_result
            user.last_request = now()
            # 加update_fields减少数据库写入开销
            user.save(update_fields=['last_request'])
            return user, validated_token
        return None

之后在项目配置文件中替换默认的JWT认证类:

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        '你存放该类的模块路径.UpdateLastRequestJWTAuthentication',
        # 其他原有认证类保留即可
    )
}

如果同时兼容session等其他认证方式,对应重写对应认证类的authenticate方法添加更新逻辑即可。

方案2:中间件内主动解析JWT(必须使用中间件的场景)

如果业务逻辑要求必须通过中间件实现,可以在中间件内手动解析请求头的JWT token,提前完成身份校验:

from django.utils.timezone import now
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
from rest_framework_simplejwt.tokens import AccessToken

class LastRequestMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 从请求头提取JWT token
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        if auth_header.startswith('Bearer '):
            token_str = auth_header.split(' ')[1]
            try:
                access_token = AccessToken(token_str)
                user = access_token.get_user()
                user.last_request = now()
                user.save(update_fields=['last_request'])
                # 可选:将解析到的用户赋值给request,供后续逻辑复用
                request.user = user
            except (InvalidToken, TokenError):
                # token无效直接跳过即可
                pass
        response = self.get_response(request)
        return response

该方案的中间件仅需要放在CommonMiddleware之后即可,不依赖AuthenticationMiddleware。

内容的提问来源于stack exchange,提问作者sandders_on

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:39:04