аутентификация () не работает должным образом для django

#python #django

#python #django

Вопрос:

В основном то, что я сделал до сих пор, — это создать страницу регистрации, где пользователь вводит свое имя пользователя и пароль, затем этот пароль сохраняется в виде хэшированного пароля (md5 hasher). Проблема, с которой я сталкиваюсь, заключается в входе в систему. Пользователь вводит свое имя пользователя и пароль, затем пароль аутентифицируется с помощью метода authenticate() в django. Проблема в том, что authenticate() возвращает None вместо сопоставления пользователя и пароля в базе данных. Я не знаю, влияет ли это на что-либо, но я использую PostgreSQL.

models.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

 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

 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)
 

Ответ №1:

Почему вы заменяете модель пользователя, которую предоставляет django, если у вас те же атрибуты? Это делается на случай, если вы хотите расширить или добавить новые свойства для пользователя, например, номер лицензии, аватар, должность.

В любом случае, ваш authenticate(), возможно, не работает, потому что вы не зарегистрировали свою новую модель в settings.py .

 AUTH_USER_MODEL = 'name_of_the_app.User'
 

Я рекомендую вам взглянуть на официальную документацию
https://docs.djangoproject.com/en/3.1/topics/auth/customizing /

Другое дело, что это может быть ваш сервер аутентификации:

Попробуйте:

settings.py

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

Где вы хотите, например 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
 

Как вы можете видеть, вы также можете войти в систему с помощью электронной почты

Комментарии:

1. У меня уже есть AUTH_USER_MODEL в моем settings.py вот почему я действительно в замешательстве

2. @kixsmart Теперь проверьте серверную часть аутентификации:

3. да, чувак, в чем проблема, ничего не работает. Idk, если это имеет значение, но пароль хэшируется с помощью md5