Как решить ошибку 401 несанкционированный вход в систему DRF простой вход пользователя jwt

Я создаю API-интерфейсы аутентификации DRF для пользователей Abstract Base в своем проекте Django и использую простой JWT. API-интерфейсы регистрации и проверки электронной почты работают нормально, но когда я пытаюсь войти в систему, используя учетные данные действительного пользователя, я получаю сообщение об ошибке 401 неавторизованный доступ.

пользовательская модель пользователя в models.py

      class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=255, unique=True,db_index=True)
    email = models.EmailField(max_length=255, unique=True,db_index=True)
    is_verified = models.BooleanField(default=False)
    is_active = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now_add=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELD = ['username']

    objects = UserManager()

    def __str__(self):
        return self.email

    def tokens(self):
        refresh = RefreshToken.for_user(self)
        return{
            'refresh':str(refresh),
            'access': str(refresh.access_token)
        }

Вот мое представление на основе класса входа в views.py:

      class LoginAPIView(generics.GenericAPIView):
    serializer_class = LoginSerializer
    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)

        return Response(serializer.data, status=status.HTTP_200_OK)

Вот LoginSerializer в serializers.py

      class LoginSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(max_length=255, min_length=3)
    password = serializers.CharField(max_length=68, min_length=8, write_only=True)
    username = serializers.CharField(max_length=255, min_length=3, read_only = True)
    tokens = serializers.CharField(max_length=68, min_length=8, read_only = True)


    class Meta:
        model = User
        fields = ['email', 'password', 'username', 'tokens']


    def validate(self, attrs):
        email = attrs.get('email', '')
        password = attrs.get('password', '')
  
        user = auth.authenticate(email=email, password=password)
        if not user:
            raise AuthenticationFailed('Invalid Credentials, try again!')

        if not user.is_active:
            raise AuthenticationFailed('Acccount disabled, please contact admin')

        if not user.is_verified:
            raise AuthenticationFailed('Email is not verified')
                

        return {
            'email': user.email,
            'username': user.username,
            'tokens': user.tokens

        }
        return super().validate(attrs)

В settings.py единственные настройки, относящиеся к DRF-simple Jwt:

      REST_FRAMEWORK = {
    'NON_FIELD_ERRORS_KEY': 'error',
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    )
}

Таким образом, возникает ошибка «Неверные учетные данные», что означает, что данные о пользователе не существуют, хотя пользователи действительно существуют, когда я проверяю базу данных.

Кто-нибудь, пожалуйста, помогите.

2 ответа

Итак, после долгих гуглений и головной боли я снова прочитал документацию Simple Jwt , и, как оказалось, ошибка 401 возникает, если пользователь не активен. В моем models.pyвыше, по умолчанию мой пользователь и . Вид изменился is_verifiedк Trueпосле того, как пользователи подтвердили свою электронную почту, но их is_activeостался Falseотсюда и ошибка 401. Мое решение заключалось в добавлении is_active=Trueкогда пользователь подтверждает свою электронную почту: вот VerifyEmailпосмотреть в views.py

      class VerifyEmail(views.APIView):
    serializer_class = EmailVerificationSerializer

    token_param_config = openapi.Parameter('token',in_=openapi.IN_QUERY, description='Description', type=openapi.TYPE_STRING)

    @swagger_auto_schema(manual_parameters=[token_param_config])
    def get(self, request):
        token = request.GET.get('token')
        try:
            payload = jwt.decode(token,settings.SECRET_KEY, algorithms=['HS256'])
            user = User.objects.get(id=payload['user_id'])
            if not user.is_verified:
                user.is_verified = True
                user.is_active = True           # New
                user.save()
            return Response({'email': 'Succesfully activated'}, status = status.HTTP_200_OK)

        except jwt.ExpiredSignatureError as identifier:
            return Response({'error': 'Activation Expired'}, status= status.HTTP_400_BAD_REQUEST)
        except jwt.exceptions.DecodeError as identifier:
            return Response({'error': 'Invalid token'}, status=status.HTTP_400_BAD_REQUEST)

Это сработало для меня.

Что вы хотите, так это исключить ваш вход в систему из проверки подлинности всего проекта, которую вы добавили в settings.py.

      class LoginAPIView(generics.GenericAPIView):
    permission_classes = ()
    authentication_classes = ()
    serializer_class = LoginSerializer

    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)

        return Response(serializer.data, status=status.HTTP_200_OK)
Другие вопросы по тегам