使用Django REST Framework JWT认证时,如何将request.user替换为代理用户模型TheDude
解决方法:重写JWT认证类的
authenticate_credentials方法 你的思路方向是对的——通过自定义JWT认证类替换默认的用户获取逻辑,但只设置user_model可能不够稳妥。我们需要在认证过程中明确用代理模型TheDude获取用户实例,确保返回的是代理模型对象而非原User对象。
步骤1:完善自定义JWT认证类
修改你的MyCustomJWTAuthentication,直接重写authenticate_credentials方法,明确指定用TheDude查询用户:
from rest_framework_jwt.authentication import JWTAuthentication from rest_framework_jwt.exceptions import InvalidToken, AuthenticationFailed from myapp.models import TheDude class MyCustomJWTAuthentication(JWTAuthentication): def authenticate_credentials(self, payload): try: user_id = payload['user_id'] except KeyError: raise InvalidToken('Invalid payload') try: # 直接用代理模型TheDude获取用户实例 user = TheDude.objects.get(pk=user_id) except TheDude.DoesNotExist: raise AuthenticationFailed('User not found') if not user.is_active: raise AuthenticationFailed('User is inactive') return (user, payload)
这种方式绕开了父类中get_user_model()的逻辑,完全掌控用户实例的获取过程,确保返回的是TheDude类型的对象。
步骤2:确认配置优先级
在settings.py中,确保自定义认证类在DEFAULT_AUTHENTICATION_CLASSES中是唯一的JWT认证类,或者放在最前面(避免默认的JWT认证类先执行覆盖结果):
REST_FRAMEWORK = { # 其他配置项... 'DEFAULT_AUTHENTICATION_CLASSES': ( 'myapp.authentication.MyCustomJWTAuthentication', # 移除默认的'rest_framework_jwt.authentication.JSONWebTokenAuthentication' ), }
步骤3:验证序列化器中的用户类型
现在你的TestSerializer中,打印type(self.context['request'].user)应该会输出<class 'myapp.models.TheDude'>。如果仍未生效,可以检查:
- 视图是否继承了DRF的
APIView或其子类(确保DRF的认证流程被触发) - 自定义视图中是否手动将request传入序列化器的context(通用视图会自动传入,自定义视图需要添加
context={'request': request})
为什么之前的方法没生效?
你之前在__init__中设置self.user_model = TheDude理论上可行,但可能因为父类JWTAuthentication的初始化逻辑、DRF认证流程的优先级问题,导致这个实例属性没有被正确读取。直接重写authenticate_credentials是更可靠的方案,完全避免了这类潜在问题。
内容的提问来源于stack exchange,提问作者Rudiger
相关产品推荐
相关产品推荐

