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

查看:56
本文介绍了中间件更新 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天全站免登陆