Django authenticate函数返回None,尽管User不是None

yh2wf1be  于 2023-08-08  发布在  Go
关注(0)|答案(1)|浏览(109)

我试图使自定义用户使用电子邮件而不是用户名登录,但验证(电子邮件=电子邮件,密码=密码)返回无,虽然用户存在

class CustomUserManager(UserManager):
    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')
        return self.create_user(email, password, **extra_fields)

class User(AbstractUser):
    email    = models.EmailField(max_length=254, unique=True)
    username = None
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = [] 
    objects = CustomUserManager() # use the custom manager
    
    def __str__(self):
        return self.email

字符串
网址:Views.py

class SignUp(CreateView):
    form_class    = SignUpForm
    template_name = 'signup.html' 
    
    def form_valid(self, form):
        email     = form.cleaned_data['email']
        password1 = make_password(form.cleaned_data['password1'])
        password2 = make_password(form.cleaned_data['password2'])
        user      = User(email=email, password=password1, username=email)
        user      = user.save()
        print("User created!")
        user      = authenticate(username=email, password=password1)
        login(self.request, user)
        return redirect('home')


class LoginView(FormView):
    template_name = 'login.html'
    form_class    =  LoginForm 

    def form_valid(self, form):
        email    = form.cleaned_data['email']
        password = make_password(form.cleaned_data['password'])
        print(email, password) # for debugging purposes
        user     = authenticate(username=email, password=password)
        print(user) # for debugging purposes
        if user is not None:
            print('do')
            login(self.request, user)
            return redirect('home')
        else:
            messages.info(self.request, 'invalid username or password')
            return redirect('login')


网址:backends.py

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class EmailBackend(ModelBackend):
    def authenticate(self, request, password=None, email=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=email)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None


settings.py
AUTH_USER_MODEL = 'accounts.User'
AUTHENTICATION_BACKENDS = [

'accounts.backends.EmailBackend',


]
网址:forms.py

from .models import User
from django.contrib.auth.forms import UserCreationForm
from django import forms

class SignUpForm(UserCreationForm): 
    email     = forms.EmailField(widget=forms.EmailInput(
        attrs={'class'      : 'form-control', 
               'type'       : "text",
               'class'      : "form-control",
               'placeholder': "Email"}))
    password1 = forms.CharField(min_length=8, label='Password', widget=forms.PasswordInput(
        attrs={'id'         : "password-field",
               'class'      : 'form-control', 
               'type'       : "password",
               'class'      : "form-control",
               'placeholder': "Password",
               'toggle'     : "#password-field",}))
    password2 = forms.CharField(min_length=8, label='Confirm Password', 
                               widget=forms.PasswordInput(
        attrs={'id'         :"password-field",
               'class'      : 'form-control', 
               'type'       : "password",
               'class'      : "form-control",
               'placeholder': "Confirm Password",}))
    class Meta:
        model  = User
        fields = ('email', 'password1', 'password2')

class LoginForm(forms.Form):
    email     = forms.CharField(widget=forms.EmailInput(
        attrs={'class'      : 'form-control', 
               'type'       : "text",
               'class'      : "form-control",
               'placeholder': "Email"}))
    password  = forms.CharField(min_length=8, label='Password', widget=forms.PasswordInput(
        attrs={'id'         : "password-field",
               'class'      : 'form-control', 
               'type'       : "password",
               'class'      : "form-control",
               'placeholder': "Password",
               'toggle'     : "#password-field",}))
    class Meta:
        model = User
        fields = ('email', 'password',)


我想知道为什么user的值是None。我确信电子邮件和密码与数据库匹配。

mqkwyuun

mqkwyuun1#

问题是您对make_passwordcheck_password的使用。
LoginView不应该做make_password。这是将原始密码转换为加密密码的函数。由于您只想在数据库中存储加密的密码,因此您希望在注册新用户时使用此功能**,而不是在登录用户时使用**。
check_password的函数需要两个必参数。这是您的代码中尚未遇到的错误。
您的LoginView应该将原始密码传递给您的authenticate方法(现在您正在传递加密的密码)。然后,在authenticate方法中,您应该检查原始密码与来自数据库的加密密码。这是您需要传递给check_password的两个参数。如果您将加密的密码传递给check_password方法,它将再次加密加密的密码。您将看到check_password("xyz", "xyz")不是True

class LoginView(FormView):
    template_name = 'login.html'
    form_class    =  LoginForm 

    def form_valid(self, form):
        email    = form.cleaned_data['email']
        password = form.cleaned_data['password']  # pass the raw one
        print(email, password) # for debugging purposes
        user     = authenticate(email=email, password=password) # change username to email here
        print(user) # for debugging purposes
        if user is not None:
            print('do')
            login(self.request, user)
            return redirect('home')
        else:
            messages.info(self.request, 'invalid username or password')
            return redirect('login')

个字符

相关问题