中间件更新request.user,但在视图中request.user变为AnonymousUser [英] middleware updates request.user, but request.user becomes AnonymousUser in view

查看:92
本文介绍了中间件更新request.user,但在视图中request.user变为AnonymousUser的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个简单的JWT中间件来从JWT中获取用户.方法 get_user_from_jwt 返回一个User对象.

I wrote a simple JWT middleware to get user from the JWT. The method get_user_from_jwt returns a User object.

# app.middlewares.py

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

    def __call__(self, request):
        self.process_request(request)
        return self.get_response(request)

    def process_request(self, request):
        request.user = self.get_user_from_jwt(request.headers)

    def get_user_pk_from_jwt(self, auth_header: str) -> int:
        _, token = auth_header.split(' ')
        decoded_payload = jwt.decode(token, settings.SECRET_KEY)
        user_pk = decoded_payload.get('user_id', None)
        return user_pk

    def get_user_from_jwt(self, auth_header: str) -> User:
        auth_header = headers.get('Authorization', None)
        if auth_header:
            try:
                user_pk = self.get_user_pk_from_jwt(auth_header)
                user = get_object_or_404(User, pk=user_pk)
                return user
            except Exception as error:
                logging.error(f'Error decoding JWT due to: {str(error)}')
                raise AuthenticationFailed
        else:
            raise NotAuthenticated

在设置中:

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'app.middlewares.JwtMiddleware',
]

我登录时,在中间件级别将 request.user 设置为正确的User实例,但是一旦查看, request.user 便成为AnonymousUser.我也尝试过切换中间件的顺序.有什么想法可以使用中间件更新视图中的request.user表示什么吗?

When I log, request.user is set to the proper User instance at the middleware level, but once at a view, request.user becomes AnonymousUser. I tried switching the orders of the middlewares too. Any ideas how I can update what request.user means inside my views using a middleware?

推荐答案

如果您在Django rest框架中使用JWT令牌身份验证,则需要更新身份验证后端.验证用户身份后,将自动设置request.user.因此,如果您不对用户进行身份验证,那么您的request.user将被AnonymousUser覆盖.

If you are using JWT token authentication with Django rest framework, then you need to update your authentication backends. The request.user is set automatically, when a user is authenticated. So if you are not authenticating the user, your request.user will be over-written by AnonymousUser.

您需要编写一个身份验证类,例如JWTAuth,它应该继承BaseAuthetication.

You need to write an authentication Class, for example, JWTAuth, which should inherit the BaseAuthetication.

from rest_framework import authentication, exceptions

class JWTAuth(authentication.BaseAuthentication):
    authentication_header_prefix = 'Bearer'

    def authenticate(self, request):
        request.user = None
        auth_header = authentication.get_authorization_header(request).split()
        auth_header_prefix = self.authentication_header_prefix.lower()

        if not auth_header:
            return None

        prefix = auth_header[0].decode('utf-8')
        token = auth_header[1].decode('utf-8')

        if prefix.lower() != auth_header_prefix:
            return None

        return self._authenticate_credentials(request, token)

    def _authenticate_credentials(self, request, token):
        try:
            payload = jwt.decode(token, settings.SECRET_KEY)
        except:
            msg = 'Invalid authentication. Could not decode token.'
            raise exceptions.AuthenticationFailed(msg)

        try:
            user = User.objects.get(pk=payload['id'])

        except User.DoesNotExist:
            msg = 'No user matching this token was found.'
            raise exceptions.AuthenticationFailed(msg)

        if not user.is_active:
            msg = 'This user has been deactivated.'
            raise exceptions.AuthenticationFailed(msg)

        return user, token

在您的设置文件中

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
                         'JWTAuth',
    )

如果您还尝试自定义登录过程,则必须在设置文件中更新AUTHENTICATION_BACKENDS.

If you are also trying to customize your Login process, then you will have to update AUTHENTICATION_BACKENDS in your settings file.

这篇关于中间件更新request.user,但在视图中request.user变为AnonymousUser的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆