【问题标题】:check password always returns false django检查密码总是返回 false django
【发布时间】:2021-06-24 08:18:03
【问题描述】:

我使用 django 并将用户密码存储为使用 make_password 创建的散列值。当我运行 check_password 时,我总是得到一个错误的返回,我不知道如何解决这个问题。

任何帮助将不胜感激。

我的用户注册如下所示:

def user_reg_view(request):
    form = UserForm(request.POST or None)
    if form.is_valid():
        password = hashers.make_password(form.cleaned_data.get('password'))
        fname = form.cleaned_data.get('first_name')
        lname = form.cleaned_data.get('last_name')
        email = form.cleaned_data.get('email')
        company_id = form.cleaned_data.get('company')
        User.objects.create_user(
            email = email,
            password=password,
            first_name = fname,
            last_name = lname,
            username = email,
            company_id = company_id)
        form = UserForm()
    var = {'form': form}
    return render(request, 'user_registry.html', var)

我失败的登录功能部分看起来像这样(假设用户存在并且输入的密码始终相同):

def login_view(request):
    form = LoginForm(request.POST or None)
    if form.is_valid():

        username = form.cleaned_data.get('username')
        user = User.objects.get(username=username)
        password = form.cleaned_data.get('password')
        encoded_password =  user.password
        print(hashers.make_password(password) == user.password)
        #returns false
        print(hashers.check_password(password=password, encoded=hashers.make_password(password), setter=None))
        #returns true
        print(hashers.check_password(password=password, encoded=encoded_password))
        # returns false

我不明白第一次打印与第二次打印有何不同,当然每次生成的密码哈希对于相同的字符串都不同,但 check_password 不应该能够处理吗?

如果错误可能出现在传递的寄存器形式值中,这里还有一个该函数的 sn-p:

class UserForm(forms.ModelForm):
    company = forms.CharField(max_length=50, label='', widget=forms.TextInput(attrs={'placeholder': 'your company'}))
    first_name = forms.CharField(max_length=30, label='', widget=forms.TextInput(attrs={'placeholder': 'first name'}))
    last_name = forms.CharField(max_length=30, label='', widget=forms.TextInput(attrs={'placeholder': 'last name'}))
    email = forms.CharField(max_length=40, label='', widget=forms.TextInput(attrs={'placeholder': 'email'}))
    password1 = forms.CharField(
        strip=False,
        widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
        validators=[validate_password],
        label='password')
    password2 = forms.CharField(
        label= 'please confirm password',
        widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
        strip=False
    )

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email']
        
    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError('password_mismatch')
        return password2

【问题讨论】:

    标签: django authentication password-hash


    【解决方案1】:

    create_user 方法对作为参数传递给它的密码进行哈希处理。这意味着您在将纯文本密码存储到数据库之前将其散列 两次。此外无需使用hashers.check_password,只需使用authenticate function - Django docs

    所以您的注册视图将是:

    def user_reg_view(request):
        form = UserForm(request.POST or None)
        if form.is_valid():
            password = form.cleaned_data.get('password')
            fname = form.cleaned_data.get('first_name')
            lname = form.cleaned_data.get('last_name')
            email = form.cleaned_data.get('email')
            company_id = form.cleaned_data.get('company')
            User.objects.create_user(
                email = email,
                password=password,
                first_name = fname,
                last_name = lname,
                username = email,
                company_id = company_id)
            form = UserForm()
        var = {'form': form}
        return render(request, 'user_registry.html', var)
    

    还有你的登录视图:

    from django.contrib.auth import authenticate, login
    
    
    def login_view(request):
        form = LoginForm(request.POST or None)
        if form.is_valid():
    
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            user = authenticate(username=username, password=password)
            if user is not None:
                login(request, user) # login if valid credentials
        # other code
    

    【讨论】:

    • 非常感谢!该错误与往常一样是我监督的一个小错误...我正在存储一个不存在的“密码”值,而我应该存储由我的用户表单(注册表单)返回的“密码2”
    【解决方案2】:

    双重散列是问题之一,另一个问题是我在不知不觉中散列了一个 None 值(而不是实际输入的密码)。

    在我的注册表单(用户表单)中,我使用密码 1 和密码 2,匹配它们后我返回密码 2。但是,在我创建用户的 user_reg_view 中,我正在设置密码,如下所示:

    password = form.cleaned_data.get('password')
    

    这应该是密码 2 或密码 1,密码设置为 None 并且没有抛出错误。

    【讨论】:

      【解决方案3】:

      我相信 Django 在你调用create_user() 时再次对你提供的值进行哈希处理,你可以查看this answer,它说你可以先使用create() 然后save() 密码原样,无需散列您提供的值。

      【讨论】:

        猜你喜欢
        • 2011-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-20
        • 2019-08-29
        相关资源
        最近更新 更多