凭证不正确

时间:2019-08-06 17:49:31

标签: django django-models django-rest-framework django-forms django-views

我创建了自AbstractBaseUser扩展的自定义用户模型。我尝试使用rest框架将此模型与API连接 寄存器EndPints,getUser和注销工作正常。但是,当我尝试登录用户时,它会显示此消息“凭据不正确”

我尝试发现问题,但发现该方法对某些Resnes无效

这是我的密码

urls.py

from django.urls import path, include
from knox import views as knox_views

# import views
from .views import RegisterAPI, LoginAPI, UserAPI

urlpatterns = [
  path('api/auth', include('knox.urls')),
  path('api/auth/register', RegisterAPI.as_view()),
  path('api/auth/login', LoginAPI.as_view()),
  path('api/auth/user', UserAPI.as_view()),
  path('api/auth/logout', knox_views.LogoutView.as_view(), name='knox-logout'),
]

自定义用户模型

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

# cerate user manger (replace old user Table with User Table that we cerated)
class UserManager(BaseUserManager):
    def create_user(self, phone, password=None, username=None,is_staff=False, is_admain=False, active=True,**extra_fields):
        if not phone:
            raise ValueError("User must have a phone number")
        if not password:
            raise ValueError("User must have password")

        user = self.model(phone=phone)
        user.set_password(password)
        user.username = username
        user.staff = is_staff
        user.admain = is_admain
        user.active = active
        user.save(using=self.db)
        return user

    def create_staff(self, phone, password=None, username=None,**extra_fields):
        user = self.create_user(phone, password=password,username=username,staff=True)
        return user

    def create_superuser(self, phone, password=None, username=None,**extra_fields):
        user = self.create_user(phone,password=password,username=username)
        user.staff = True
        user.admin = True
        user.save(using=self._db)
        return user

# Cerate User Model the will every user will inherit from it
class User(AbstractBaseUser):
    phone = models.CharField(max_length=9, unique=True)
    username = models.CharField(max_length=60)
    active = models.BooleanField(default=True)   # Can login
    staff = models.BooleanField(default=False)
    admin = models.BooleanField(default=False)
    date_joined = models.DateTimeField(auto_now_add=True)
    date_of_birth = models.DateField(auto_now_add=True)
    USERNAME_FIELD = 'phone'
    REQUIRED_FIELDS = ['username']

    object = UserManager()

    def __str__(self):
        return self.username

    def get_full_name(self):
        return self.phone

    def get_short_name(self):
        return self.username

    def is_staff(self):
        return self.is_staff

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True


    @property
    def is_superuser(self):
        return self.admin

    @property
    def is_active(self):
        return self.active

    @property
    def is_staff(self):
        return self.staff



API.py


from rest_framework import generics, permissions
from rest_framework.response import Response
from knox.models import AuthToken

# import serializers
from .serializers import UserSerializer, RegisterSerializer, LoginSerializer

# Regester API
class RegisterAPI(generics.GenericAPIView):
  serializer_class = RegisterSerializer

  def post(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    user = serializer.save()
    return Response({
      "user": UserSerializer(user, context=self.get_serializer_context()).data,
      "token": AuthToken.objects.create(user)[1]
    })


# Login API
class LoginAPI(generics.GenericAPIView):
  serializer_class = LoginSerializer

  def post(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    user = serializer.validated_data
    return Response({
      "user": UserSerializer(user, context=self.get_serializer_context()).data,
      "token": AuthToken.objects.create(user)[1]
    })

# Get User API
class UserAPI(generics.RetrieveAPIView):
  permission_classes = [permissions.IsAuthenticated,]
  serializer_class = UserSerializer

  def get_object(self):
    return self.request.user

serializers.py


from rest_framework import serializers
from django.contrib.auth import authenticate


# import user Model
from django.contrib.auth import get_user_model

User = get_user_model()

# User Serializer
class UserSerializer(serializers.ModelSerializer):
  class Meta:
    model = User
    fields = ('id', 'phone', 'username', 'active', 'staff', 'admin')


# Register Serializer
class RegisterSerializer(serializers.ModelSerializer):
  class Meta:
    model = User
    fields = ('id', 'phone', 'username', 'active', 'staff', 'admin', 'password')
    extra_kwargs = {'password': {'write_only': True}}

  def create(self, validated_data):
    user = User.object.create_user(validated_data['phone'], validated_data['username'],validated_data['password'])

    return user


# Login Serializer
class LoginSerializer(serializers.Serializer):
  phone = serializers.CharField()
  password = serializers.CharField()

  print("-=-=-=-=-=--=-=-=-=--==-=---")
  def validate(self, data):
    user = authenticate(**data)
    #user = authenticate(phone=data[phone], password=data[password])
    # not comming her ....... why ?!!!!
    print("next !!")
    print("-=-=-=-=-=--=-=-=-=--==-=---")
    if user and user.is_active:
      return user

    raise serializers.ValidationError('Incorrect Credentials')

API EndPoint返回给我


{
    "non_field_errors": [
        "Incorrect Credentials"
    ]
}

1 个答案:

答案 0 :(得分:0)

在序列化器中,您正在验证phonepassword字段,但是您正在使用django-authentication函数来验证用户。通常,django身份验证需要usernamepassword来验证用户,但是您的序列化程序似乎没有username字段。

如果要使用身份验证功能,首先需要找出与该电话字段关联的用户实例。重要的一点是,由于这是一个唯一字段,因此如果用户确定退出,则需要验证该用户。

# Login Serializer
class LoginSerializer(serializers.Serializer):
  phone = serializers.CharField()
  password = serializers.CharField() 


  def validate(self, data):

    try:
        user = User.objects.get(phone=data['phone'])
    except User.DoesNotExist:
        raise serializers.ValidationError('Incorrect Credentials')

    user = authenticate(username=user.username, password=data['password'])

    if user and user.is_active:
      return user

    raise serializers.ValidationError('Incorrect Credentials')

另一个重要的一点是,您需要确保您的用户处于活动状态。