【问题标题】:Django JWT authentication - user is anonymous in middlewareDjango JWT 身份验证 - 用户在中间件中是匿名的
【发布时间】:2018-11-20 10:29:49
【问题描述】:

我正在使用 Django JWT 在我的项目中启动身份验证系统。 另外,我有一个中间件,问题是其中的用户由于某种原因是匿名的,而在视图中我可以通过request.user 访问正确的用户。这个问题让我发疯,因为前段时间这段代码运行良好!这是 JWT 的错误还是我做错了什么?

class TimezoneMiddleware(MiddlewareMixin):
         def process_request(self, request):
            # request.user is ANONYMOUS HERE !!!!
            if not request.user.is_anonymous:
                  tzname = UserProfile.objects.get(user = request.user).tz_name
                  if tzname:
                       timezone.activate(pytz.timezone(tzname))

相关settings.py模块:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_RENDERER_CLASSES': (
        'djangorestframework_camel_case.render.CamelCaseJSONRenderer',
        # Any other renders
    ),

    'DEFAULT_PARSER_CLASSES': (
        'djangorestframework_camel_case.parser.CamelCaseJSONParser',
        # Any other parsers
    ),
}

JWT_AUTH = {
    'JWT_ENCODE_HANDLER':
    'rest_framework_jwt.utils.jwt_encode_handler',

    'JWT_DECODE_HANDLER':
    'rest_framework_jwt.utils.jwt_decode_handler',

    'JWT_PAYLOAD_HANDLER':
    'rest_framework_jwt.utils.jwt_payload_handler',

    'JWT_PAYLOAD_GET_USER_ID_HANDLER':
    'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',

    'JWT_RESPONSE_PAYLOAD_HANDLER': 'rest_framework_jwt.utils.jwt_response_payload_handler', 
    # 'rest_authentication.views.jwt_response_payload_handler',
    'JWT_SECRET_KEY': SECRET_KEY,
    'JWT_PUBLIC_KEY': None,
    'JWT_PRIVATE_KEY': None,
    'JWT_ALGORITHM': 'HS256',
    'JWT_VERIFY': True,
    'JWT_VERIFY_EXPIRATION': False,
    'JWT_LEEWAY': 0,
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
    'JWT_AUDIENCE': None,
    'JWT_ISSUER': None,
    'JWT_ALLOW_REFRESH': False,
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
    'JWT_AUTH_HEADER_PREFIX': 'JWT',
}

我也遇到了帮助我检索实际用户的资源,但是!我仍然无法设置时区(timezone.activate(pytz.timezone(tzname)) 似乎被忽略了。

【问题讨论】:

    标签: django-middleware django-rest-framework-jwt


    【解决方案1】:

    @Atul Mishra:谢谢!将您的版本更改为最新的 drf-jwt 包 (1.17.2)。似乎当前的 github 存储库从 this 移动到 here

    from django.contrib.auth.middleware import get_user
    from django.utils.functional import SimpleLazyObject
    from rest_framework_jwt.authentication import JSONWebTokenAuthentication
    
    
    class JWTAuthenticationInMiddleware(object):
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            request.user = SimpleLazyObject(lambda:self.__class__.get_jwt_user(request))
            return self.get_response(request)
    
        @staticmethod
        def get_jwt_user(request):
            # Already authenticated
            user = get_user(request)
            if user.is_authenticated:
                return user
    
            # Do JTW authentication
            jwt_authentication = JSONWebTokenAuthentication()
    
            authenticated = jwt_authentication.authenticate(request)
            if authenticated:
                user, jwt = authenticated
    
            return user
    

    【讨论】:

      【解决方案2】:

      是的,这个问题是由 JWT 引起的。你可以查看它的讨论https://github.com/GetBlimp/django-rest-framework-jwt/issues/45 要解决这个问题,你必须创建一个自定义中间件来设置request.user。这是我在代码中使用的一个:

      from django.contrib.auth.middleware import get_user
      from django.utils.functional import SimpleLazyObject
      from rest_framework_jwt.authentication import JSONWebTokenAuthentication
      
      
      class JWTAuthenticationMiddleware(object):
          def __init__(self, get_response):
              self.get_response = get_response
      
          def __call__(self, request):
              request.user = SimpleLazyObject(lambda:self.__class__.get_jwt_user(request))
              return self.get_response(request)
      
          @staticmethod
          def get_jwt_user(request):
              user = get_user(request)
              if user.is_authenticated:
                  return user
              jwt_authentication = JSONWebTokenAuthentication()
              if jwt_authentication.get_jwt_value(request):
                  user, jwt = jwt_authentication.authenticate(request)
              return user
      

      将其包含在中间件中。它应该高于所有使用request.user 的中间件。

      【讨论】:

        猜你喜欢
        • 2020-05-02
        • 2017-04-20
        • 2021-04-11
        • 2018-11-05
        • 2014-08-09
        • 2018-05-21
        • 2017-12-29
        • 2018-11-26
        • 1970-01-01
        相关资源
        最近更新 更多