【问题标题】:Cannot use User in Django Rest Framework Custom Request middleware using JWT token after created new middleware创建新中间件后,无法使用 JWT 令牌在 Django Rest Framework 自定义请求中间件中使用用户
【发布时间】:2020-03-25 15:05:40
【问题描述】:

我想在 Django Rest Framework 自定义中间件中使用request.user。 它返回 AnonymousUser,但我失败了。

我创建了返回真实用户的新自定义中间件。

from django.contrib.auth.middleware import get_user
from django.utils.functional import SimpleLazyObject
from rest_framework_jwt.authentication import JSONWebTokenAuthentication

class AuthenticationMiddlewareJWT(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

在中间件之上,jwt_authentication.get_jwt_value(request),它总是返回 None。

如何修复它并在自定义中间件中使用request.user?

【问题讨论】:

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


    【解决方案1】:

    尝试使用simplejwt pip install djangorestframework-simplejwt

    尝试在 middleware.py 中执行此操作

    from django.contrib.auth.middleware import get_user
    from django.utils.functional import SimpleLazyObject
    from rest_framework_simplejwt.authentication import JWTTokenUserAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    import jwt
    from django.conf import settings
    from django.contrib.auth.models import User, AnonymousUser
    
    
    
    class JWTAuthenticationMiddleware(object):
        # print("a")
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            request.user = SimpleLazyObject(lambda:self.__class__.get_jwt_user(request))
            # print(request.user)
            return self.get_response(request)
    
    
        # def process_request(self, request):
        #     request.user = SimpleLazyObject(lambda: self.__class__.get_jwt_user(request))
    
            
    
        @staticmethod
        def get_jwt_user(request):
            # print(request.user)
            # user = get_user(request)
            # user = AnonymousUser()
            try:
                access_token = request.COOKIES['jwtt']
            except KeyError:
                raise AuthenticationFailed(
                    "Key missing try to login" \
                        " again (you logged out by timeout)"
                )
            if not access_token:
                raise AuthenticationFailed(
                    'unaunticated access token missing'
                )
                # user = AnonymousUser()
            try:
                payload = jwt.decode(
                    access_token,
                    settings.SECRET_KEY,
                    algorithms=['HS256']
                    )
                user = User.objects.get(id=payload['user_id'])
            except jwt.ExpiredSignatureError:
                # raise AuthenticationFailed(
                #     'unautneticated'
                # )
                user = AnonymousUser()
           
    

    我的views.py

    from rest_framework.exceptions import AuthenticationFailed
    from rest_framework.response import Response
    from rest_framework.views import APIView
    from rest_framework import status, generics
    from rest_framework.permissions import AllowAny
    from django.conf import settings
    
    import jwt
    from django.contrib.auth.models import User
    from .serializers import (
        UserListSerializer, UserRegistrationSerializer,
        UserLoginSerializer, MyTokenObtainPairSerializer
    )
    from rest_framework_simplejwt.views import TokenObtainPairView
    from rest_framework.decorators import api_view
    from django.http import JsonResponse, response
    from termcolor import colored
    from rest_framework.settings import api_settings
    from rest_framework import permissions
    
    class MyTokenObtainPairView(TokenObtainPairView):
        serializer_class = MyTokenObtainPairSerializer
    
    @api_view(['GET'])
    def getRoutes(request):
        routes = [
            '/api/token',
            '/api/token/refresh'
        ]
        return JsonResponse(routes)
    
    
    class AuthUserRegistrationView(APIView):
        serializer_class = UserRegistrationSerializer
        permission_classes = (AllowAny,)
    
        def post(self, request):
            serializer = self.serializer_class(data=request.data)
            valid = serializer.is_valid(raise_exception=True)
            print(colored(request.user, 'red'))
    
            if valid:
                serializer.save()
                data = serializer.data
                try:
                    data.pop('password')
                except KeyError:
                    pass
                status_code = status.HTTP_201_CREATED
    
                response = {
                    'success': True,
                    'statusCode': status_code,
                    'message': 'User successfully registered!',
                    'user': data
                }
                return Response(response, status=status_code)
    
    class AuthUserLoginView(APIView):
        serializer_class = UserLoginSerializer
        permission_classes = (AllowAny,)
    
        def post(self, request):
            serializer = self.serializer_class(data=request.data)
            valid = serializer.is_valid(raise_exception=True)
            if valid:
                status_code = status.HTTP_200_OK
                response = {
                    'success': True,
                    'statusCode': status_code,
                    'message': 'login sucessfully',
                    'access': serializer.data['access'],
                    'refresh': serializer.data['refresh'],
                    'authenticatedUser': {
                        'username': serializer.data['username'],
                    }
                }
                r = Response(response)
                r.set_cookie(key='jwtt', value=serializer.data['access'])
    
                return r
    
    class UserListView(generics.ListAPIView):
        serializer_class = UserListSerializer
        permission_classes = (
            permissions.IsAuthenticatedOrReadOnly,
        )
        
        def get(self, request):
            print(colored(request.user, 'red'))
            try:
                access_token = request.COOKIES['jwtt']
            except KeyError:
                raise AuthenticationFailed(
                    "Key missing try to login " \
                        "again(you have been loged out)"
                )
            if not access_token:
                raise AuthenticationFailed(
                    'unaunticated access token missing'
                )
            
            try:
                # print(colored('start', 'blue'))
                payload = jwt.decode(access_token, 
                    settings.SECRET_KEY,
                    algorithms=['HS256']
                    )
                # print(colored(access_token, 'red'))
            except jwt.ExpiredSignatureError:
                raise AuthenticationFailed(
                    'unauthenticated'
                )
            user = User.objects.get(id=payload['user_id'])
            if user:
                users = User.objects.all()
                serializer = self.serializer_class(users, many=True)
                
                status_code = status.HTTP_200_OK
                response = {
                    'success': True,
                    'status_code': status_code,
                    'message': 'Successfully fetched users',
                    'users': serializer.data
                }
                
        
                return Response(
                    response, status=status_code
                )  
        
            else:
                status_code = status.HTTP_401_UNAUTHORIZED
                response = {
                    'success': False,
                    'status_code': status_code,
                    'message': 'UserDoes not authorized'
                }
                return Response(response, status=status_code)
    
    class LogoutView(APIView):
        def get(self, request):
            response = Response()
            response.delete_cookie('jwtt')
            response.data = {
                'message': 'logout successfully'
            }
            return response
    

    我的serializers.py

    from tokenize import Token
    from django.contrib.auth import authenticate
    from django.contrib.auth.models import update_last_login
    from django.contrib.auth.models import User
    from django.http import request
    
    from rest_framework import serializers
    from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
    from rest_framework_simplejwt.tokens import RefreshToken
    
    
    class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
        @classmethod
        def get_token(cls, user):
            token = super().get_token(user)
            token['username'] = user.username
            return token
    
    
    class UserRegistrationSerializer(serializers.ModelSerializer):
        password = serializers.CharField(
            max_length=128, write_only=True,
            style = {
                'input_type': 'password',
                'placeholder': 'Password'
            }, required=True
        )
        class Meta:
            model = User
            fields = (
                'username',
                'email',
                'password'
            )
        def create(self, validated_data):
            auth_user = User.objects.create_user(
                **validated_data
            )
            return auth_user
    
    class UserLoginSerializer(serializers.Serializer):
        username = serializers.CharField(
            max_length=128
        )
        password = serializers.CharField(
            max_length=128, write_only=True
        )
        access = serializers.CharField(read_only=True)
        refresh = serializers.CharField(read_only=True)
    
        def create(self, validated_data):
            pass
    
        def update(self, instance, validated_data):
            pass
    
        def validate(self, data):
            username = data['username']
            password = data['password']
            user = authenticate(username=username, password=password)
            if user is None:
                raise serializers.ValidationError(
                    'invalid login credential'
                )
            try:
                refresh = RefreshToken.for_user(user)
                refresh_token = str(refresh)
                access_token = str(refresh.access_token)
    
                update_last_login(
                    None, user
                )
                validation = {
                    'access': access_token,
                    'refresh': refresh_token,
                    'username': user.username,
                    
                }
                return validation
            except User.DoesNotExist:
                raise serializers.ValidationError('User does not exesists')
    
    
    class UserListSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = (
                'username', 'email',
            )
    

    note every things are in account directory or you can say account app

    【讨论】:

      猜你喜欢
      • 2021-11-07
      • 2017-05-28
      • 2019-06-20
      • 2019-07-23
      • 2017-06-25
      • 2020-06-18
      • 1970-01-01
      • 2019-11-29
      • 2013-11-15
      相关资源
      最近更新 更多