Как решить ошибку 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)