Django RestFramework JWT 令牌:获取用户不存在错误

Django RestFramework JWT Token: Get User DoesNotExist error

用户被删除后,客户端的token仍然有效,直到超时。问题是 django restframwework 不处理来自已删除用户的请求并导致 500。我该如何防止这种情况?

aceback (most recent call last):
  File "/lib/python3.6/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/lib/python3.6/site-packages/django/core/handlers/base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/lib/python3.6/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/lib/python3.6/site-packages/rest_framework/views.py", line 505, in dispatch
    response = self.handle_exception(exc)
  File "/lib/python3.6/site-packages/rest_framework/views.py", line 465, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/lib/python3.6/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
    raise exc
  File "/lib/python3.6/site-packages/rest_framework/views.py", line 493, in dispatch
    self.initial(request, *args, **kwargs)
  File "/lib/python3.6/site-packages/rest_framework/views.py", line 410, in initial
    self.perform_authentication(request)
  File "/lib/python3.6/site-packages/rest_framework/views.py", line 324, in perform_authentication
    request.user
  File "/lib/python3.6/site-packages/rest_framework/request.py", line 220, in user
    self._authenticate()
  File "/lib/python3.6/site-packages/rest_framework/request.py", line 373, in _authenticate
    user_auth_tuple = authenticator.authenticate(self)
  File "/lib/python3.6/site-packages/rest_framework_jwt/authentication.py", line 33, in authenticate
    payload = jwt_decode_handler(jwt_value)
  File "/lib/python3.6/site-packages/rest_framework_jwt/utils.py", line 105, in jwt_decode_handler
    secret_key = jwt_get_secret_key(unverified_payload)
  File "/lib/python3.6/site-packages/rest_framework_jwt/utils.py", line 26, in jwt_get_secret_key
    user = User.objects.get(pk=payload.get('user_id'))
  File "/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/lib/python3.6/site-packages/django/db/models/query.py", line 431, in get
    self.model._meta.object_name

从 JWT 令牌中,您正在对其进行解码以获取 user_id - payload['user_id']。 发生错误是因为 User.objects.get(pk=payload.get('user_id')).

您可以使用 get_object_or_404 而不是 get。像这样使用它:

from django.shortcuts import get_object_or_404

payload = jwt_decode_handler(jwt_value)
user = get_object_or_404 (User, pk=payload.get('user_id'))

这会在找不到用户时引发 404 错误;这将通过您的视图和处理程序冒泡到 return 404 状态码。

Druhn Bala 的建议可行,但会 return 出现 404 错误,这对我的用例来说并不理想。相反,我想出了一个 return 的自定义响应。 ValidationError from rest_framework.exceptions 允许您发送带有自定义响应的 400 错误。

def jwt_decode_handler(token):
    options = {
        'verify_exp': api_settings.JWT_VERIFY_EXPIRATION,
    }
    # get user from token, BEFORE verification, to get user secret key
    try:
        unverified_user = jwt.decode(token, None, False)
    except User.DoesNotExist:
        raise ValidationError({"errors": ['Oops! Something went wrong, please logout and login back in!']})

        secret_key = unverified_user.securitysettings.jwt_secret #my custom way of storing a unique jwt uuid per user. 
    return jwt.decode(
        token,
        api_settings.JWT_PUBLIC_KEY or secret_key,
        api_settings.JWT_VERIFY,
        options=options,
        leeway=api_settings.JWT_LEEWAY,
        audience=api_settings.JWT_AUDIENCE,
        issuer=api_settings.JWT_ISSUER,
        algorithms=[api_settings.JWT_ALGORITHM]
    )

最后,我们将自定义解码处理程序设置为 settings.py 中的默认值。

JWT_AUTH = {
    'JWT_DECODE_HANDLER':
    'registration.decoder.jwt_decode_handler',
    ...
}