简体   繁体   English

验证()对于 django 无法正常工作

[英]authenticate() not working properly for django

Basically what I have done so far is create a registration page where the user makes their username and password, then that password is stored in as a hashed password (md5 hasher).基本上我到目前为止所做的是创建一个注册页面,用户在其中输入用户名和密码,然后将该密码存储为哈希密码(md5 hasher)。 The problem I am having is logging in. The user inputs their username and password then the password is authenticated by using authenticate() method in django.我遇到的问题是登录。用户输入他们的用户名和密码,然后使用 django 中的 authenticate() 方法对密码进行身份验证。 The problem is that authenticate() is returning None instead of matching the user and password in the database.问题是 authenticate() 返回 None 而不是匹配数据库中的用户和密码。 I dont know if this affects anything but I am using PostgreSQL.我不知道这是否会影响任何事情,但我正在使用 PostgreSQL。

models.py模型.py

class MyAccountManager(BaseUserManager):
    def create_user(self, email,username,first_name,password= None):
        if not email:
            raise ValueError('User must have an email address')
        if not username:
            raise ValueError('User must have a username')
        if not first_name:
            raise ValueError('User must have a first name')
        user= self.model(
            email=self.normalize_email(email),
            username= username,
            first_name= first_name
        )
        user.set_password(password)
        user.save(using=self._db)
        return user
    
    def create_superuser(self, email, username, first_name, password):
        user= self.create_user(
            email= self.normalize_email(email),
            username=username,
            first_name= first_name,
            password= password,
        )
        user.is_admin= True
        user.is_staff= True
        user.is_superuser= True
        user.save(using=self._db)
        return user
    
class User(AbstractBaseUser, models.Model):
    email = models.EmailField(verbose_name='email', max_length=60, unique=True)
    username = models.CharField(max_length=30, unique=True)
    date_joined = models.DateTimeField(auto_now_add=True, verbose_name='date joined')
    last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
    is_admin = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

    USERNAME_FIELD= 'username'
    REQUIRED_FIELDS= ['email','first_name']
    
    objects= MyAccountManager()
    def __str__(self):
        return self.email

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

    def has_module_perms(self, app_label):
        return True

forms.py forms.py

class LoginForm(forms.Form):
    username = forms.CharField(initial='' ,label='Username:',max_length=30)
    password = forms.CharField(max_length=20, widget=forms.PasswordInput())
    class Meta:
        model = User
        fields = ('username', 'password')
    def clean(self):
        cleaned_data = super(LoginForm, self).clean()
        confirm_password = cleaned_data.get('password')



class SignUpForm(forms.ModelForm):
    first_name = forms.CharField(required= True,initial='',max_length=20)
    last_name = forms.CharField(required=True,max_length=30, initial='')
    username = forms.CharField(max_length=30,initial='', required=True)
    password = forms.CharField(max_length= 20, initial='', widget = forms.PasswordInput())
    password2= forms.CharField(max_length=20, initial='',widget = forms.PasswordInput())
    email = forms.EmailField(max_length=60, initial='',)

    class Meta:
        model = User
        fields = ('first_name', 'last_name','username','password2','email')

    def clean(self):
        cleaned_data = super(SignUpForm,self).clean()
        password = cleaned_data.get('password')
        confirm_password = cleaned_data.get('password2')
        if(password != confirm_password):
            raise forms.ValidationError(
                'Password and Confirm Password do not match.'
            )

views.py视图.py

def signin_and_signup(request):

    if request.method == 'POST':
        logout(request)
        sign_in = LoginForm(request.POST)
        signup = SignUpForm(request.POST)
        if 'sign-in-name' in request.POST:
            if sign_in.is_valid():
                username = request.POST.get('username')
                password= request.POST.get('password')
                user = authenticate(username= username, password= password)
                if user:
                    return HttpResponse('success')
                else:
                    return HttpResponse('fail')
        elif 'sign-up-input-name' in request.POST:
            if(signup.is_valid()):
                user = signup.save(commit=False)
                nonHashed = signup.cleaned_data['password']
                varhash =  make_password(nonHashed, None, 'md5')
                user.set_password(varhash)
                user.save()

            else:
                print("Ran3<------------")
                signup = SignUpForm()
    else:
        sign_in = LoginForm()
        signup = SignUpForm()
    context = {'signin':sign_in, 'signup':signup}
    return render(request, 'home.html', context)

Why are you substituting the user model that django provides if you have the same attributes?如果你有相同的属性,你为什么要替换 django 提供的用户 model? This is done in case you want to extend or add new properties to the user, for example, license number, avatar, position.如果您想为用户扩展或添加新属性,例如许可证号、头像、position,则会执行此操作。

Anyway, your authenticate() maybe doesn't work because you haven't registered your new model in settings.py.无论如何,您的 authenticate() 可能不起作用,因为您尚未在 settings.py 中注册新的 model。

AUTH_USER_MODEL = 'name_of_the_app.User'

I recommend that you take a look at the official documentation https://docs.djangoproject.com/en/3.1/topics/auth/customizing/我建议你看一下官方文档https://docs.djangoproject.com/en/3.1/topics/auth/customizing/

Antoher thing it could be your authentication backend: Antoher 可能是您的身份验证后端:

Try:尝试:

settings.py设置.py

AUTHENTICATION_BACKENDS = [
    'name_of_the_app.admin.LoginBackend',
]

Where you want for example admin.py你想要的地方,例如 admin.py

from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q


class LoginBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:  # to allow authentication through phone number or any other field, modify the below statement
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            UserModel().set_password(password)
        except MultipleObjectsReturned:
            return models.User.objects.filter(email=username).order_by('id').first()
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user
    
    def get_user(self, user_id):
        try:
            user = UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

        return user if self.user_can_authenticate(user) else None

As you can see, you can also login with the email如您所见,您也可以使用 email 登录

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM