中间件更新 request.user,但 request.user 在视图中变为匿名用户



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

# 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在中间件级别设置为正确的用户实例,但一旦进入视图,request.user就会变成匿名用户。我也尝试切换中间件的顺序。任何想法如何使用中间件在我的视图中更新 request.user 的含义?

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

您需要编写一个身份验证类,例如 JWTAuth,它应该继承 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。

最新更新