DRF JWT 身份验证对象没有属性“id”

Posted

技术标签:

【中文标题】DRF JWT 身份验证对象没有属性“id”【英文标题】:DRF JWT Authentication object has no attribute 'id' 【发布时间】:2020-07-30 21:12:20 【问题描述】:

我正在使用库suggested by DRF (djangorestframework_simplejwt),使用安装

pip install djangorestframework_simplejwt

将其添加到 settings.py

REST_FRAMEWORK = 
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ]

从导入的视图创建两个端点

from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

urlpatterns = [
    # JWT Token
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain'),
    # get a new token before the old expires.
    path('api/token/refresh/', TokenRefreshView.as_view, name='token_refresh'),
]

在数据库中创建用户没有任何问题,并且正在对密码进行哈希处理。

如果我去http://localhost:8000/api/token/,那么得到下面的视图

使用密码发布正确的用户,然后我收到以下错误

[2020 年 4 月 17 日 12:06:51]“POST /api/token/HTTP/1.1”500 122221 内部 服务器错误:/api/token/ Traceback(最近一次调用最后一次):文件 "C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\django\core\handlers\exception.py", 第 34 行,在内部 response = get_response(request) 文件 "C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\django\core\handlers\base.py", 第 115 行,在 _get_response 中 response = self.process_exception_by_middleware(e, request) 文件“C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\django\core\handlers\base.py”, 第 113 行,在 _get_response 中 response = Wrapped_callback(request, *callback_args, **callback_kwargs) 文件 "C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\django\views\decorators\csrf.py", 第 54 行,在 Wrapped_view 中 返回 view_func(*args, **kwargs) 文件 "C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\django\views\generic\base.py", 第 71 行,在视图中 return self.dispatch(request, *args, **kwargs) File "C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework\views.py", 第 505 行,正在调度中 响应 = self.handle_exception(exc) 文件“C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework\views.py”, 第 465 行,在 handle_exception 中 self.raise_uncaught_exception(exc) 文件“C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework\views.py”, 第 476 行,在 raise_uncaught_exception 中 提高 exc 文件“C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework\views.py”, 第 502 行,正在调度中 响应 = 处理程序(请求,*args,**kwargs)文件“C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework_simplejwt\views.py”, 第 27 行,在帖子中 serializer.is_valid(raise_exception=True) 文件 "C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework\serializers.py", 第 234 行,在 is_valid 中 self._validated_data = self.run_validation(self.initial_data) 文件 "C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework\serializers.py", 第 436 行,在 run_validation 中 value = self.validate(value) 文件“C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework_simplejwt\serializers.py”, 第 73 行,有效 刷新 = self.get_token(self.user) 文件“C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework_simplejwt\serializers.py”, 第 68 行,在 get_token 中 返回 RefreshToken.for_user(user) 文件 "C:\Users\tiago\Desktop\letsgo\authenticationJwt\lib\site-packages\rest_framework_simplejwt\tokens.py", 第 161 行,在 for_user user_id = getattr(user, api_settings.USER_ID_FIELD) AttributeError: 'MyUser' object has no attribute 'id'

错误很明显,MyUser 对象没有属性 id。相反,它具有user_id 作为primary_key,如下所示

class MyUser(AbstractBaseUser):
    user_id = models.AutoField(primary_key=True, db_column='userId')
    password = models.CharField(db_column='userPassword', max_length=256)
    email = models.EmailField(verbose_name='email', max_length=100, unique=True)

问题是,我不想更改当前的 MyUser 字段。


编辑

去settings of djangorestframework_simplejwt可以阅读

DEFAULTS = 
    ...
    'USER_ID_FIELD': 'id',
    ...

所以,考虑到我不想将 MyUser primary_key 更改为 id,我去了安装 djangorestframework_simplejwt 的地方并搜索了声明 USER_ID_FIELD 的位置。

仅在 SIMPLE_JWT 的 venv\Jwt\Lib\site-packages\djangorestframework_simplejwt-4.4.0.dist-info\METADATA 中找到它。在那里,改为

  SIMPLE_JWT = 
      ...
      'USER_ID_FIELD': 'user_id',
      ...
  

然后,重新启动 venv 和 runserver。问题仍然存在。

【问题讨论】:

【参考方案1】:

我已重置 METADATA 中所做的更改,然后转到我的项目 settings.py 文件并添加

SIMPLE_JWT = 
    'USER_ID_FIELD': 'user_id'

【讨论】:

以上是关于DRF JWT 身份验证对象没有属性“id”的主要内容,如果未能解决你的问题,请参考以下文章

在 Django/DRF 中使用 JWT 身份验证并将 JWT 存储在 HttpOnly Cookie 中

DRF 简单 jwt 从用户实例获取身份验证令牌或更改用户名和密码组合

如何在 DRF 中使用身份服务器 4 验证 JWT 令牌?

Drf令牌认证密码重置

Django Rest Framework JWT 身份验证测试

在测试期间使用 Django Rest + JWT 进行身份验证