Django如何比较存储的哈希密码和明文密码

huangapple go评论67阅读模式
英文:

Django how to compare stored hash password and plain password

问题

在你的Django应用中,你已经实现了用户注册和登录功能,但目前用户只能使用经过哈希处理的密码进行登录。如果你想允许用户使用明文密码进行登录,同时仍然在数据库中存储哈希密码,可以采取以下步骤:

  1. 更改用户登录验证逻辑:

    目前,你的用户登录逻辑通过 check_password 函数来验证用户提供的密码。要支持明文密码登录,你需要进行一些修改。你可以根据用户提供的明文密码和数据库中的哈希密码进行验证。如果验证成功,用户就可以登录。

    以下是修改后的示例代码:

    def user_login(request):
        if request.method == "POST":
            user_email = request.POST['user_email']
            user_password = request.POST['user_password']
            user_details = User.objects.filter(user_email=user_email).values()
            hashed_pw = User.objects.filter(user_email=user_email).values('user_password')[0]['user_password']
            # 验证明文密码和哈希密码
            if user_details and (user_password == check_password(user_password, hashed_pw)):
                # 登录成功
                request.session['logged_in'] = True
                request.session['user_email'] = user_details[0]["user_email"]
                request.session['u_id'] = user_details[0]["user_email"]
                request.session['user_name'] = user_details[0]["user_name"]
                request.session['u_type'] = "emp"
                return HttpResponseRedirect('/user_index')
            else:
                return render(request, 'EmpLogin.html', {'msg': "0"})
        else:
            return render(request, 'EmpLogin.html')
    
  2. 更新密码存储逻辑:

    确保在用户注册时存储哈希密码,以便在登录时进行验证。这部分的代码看起来没有问题,因为你已经在注册时使用了 make_password 函数:

    user_password = pwo.generate()
    user_password1 = make_password(user_password)
    empObj = User.objects.create(user_name=user_name, user_email=user_email, user_password=user_password1, user_otj=user_otj)
    

这些步骤将允许用户使用明文密码进行登录,同时在数据库中存储哈希密码以提高安全性。请注意,使用明文密码登录会增加一些安全风险,因此需要谨慎处理用户密码。

英文:

I'm new to Django and I created function to allow admin to create users accounts. I used a password generator + make_password() function to hash the password.

Now it's sending the plain password to users email and storing it in the database hashed.

now the user is able to login with the hashed password only.

my view.py:

@admin_login_required
def add_emp(request):
    if request.method == 'POST':
        user_name = request.POST['user_name']
        user_email = request.POST['user_email']
        user_otj = request.POST['user_otj']
        user_password = pwo.generate()
        user_password1 = make_password(user_password)
        empObj = User.objects.create(user_name=user_name, user_email=user_email, user_password=user_password1, user_otj=user_otj)
        if empObj:
            subject = 'Login Info'
            message = f'Name : {user_name}, \n Email : {user_email}, \n Password : {user_password} \n FROM - AA Portal'
            email_from = settings.EMAIL_HOST_USER
            send_mail(subject, message, email_from, [user_email])
            messages.success(request, "Employee was added successfully!")
            return HttpResponseRedirect('/create-emp')
        else:
            messages.error(request, "Some error was occurred!")
            return HttpResponseRedirect('/create-emp')
    return render(request, 'AddEmp.html')

def user_login(request):
    if request.method == "POST":
        user_email = request.POST['user_email']
        user_password = request.POST['user_password']
        user_details = User.objects.filter(user_email=user_email).values()
        hashed_pw = User.objects.all().first().user_password
        checkpass = check_password(user_password, hashed_pw)

        if user_details and checkpass:
            request.session['logged_in'] = True
            request.session['user_email'] = user_details[0]["user_email"]
            request.session['u_id'] = user_details[0]["user_email"]
            request.session['user_name'] = user_details[0]["user_name"]
            request.session['u_type'] = "emp"
            return HttpResponseRedirect('/user_index')
        else:
            return render(request, 'EmpLogin.html', {'msg': "0"})
    else:
        return render(request, 'EmpLogin.html')

User model:

class User(models.Model):
    user_email = models.CharField(primary_key=True, max_length=100)
    user_role_id = models.CharField(max_length=20)
    user_password = models.CharField(max_length=20)
    user_name = models.CharField(max_length=100)
    user_avatar_path = models.CharField(max_length=300)
    user_job_title = models.TextField(blank=True, null=True)
    user_educ_qual = models.TextField(blank=True, null=True)
    user_companies = models.TextField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'user'

Any idea how to make the user login with the plain password and keep it hashed in the database?

答案1

得分: 1

这里应该可以找到你需要的一切。你需要为你的用户创建一个密码字段,这应该是清晰的。

> 如果你想通过比较明文密码与数据库中的哈希密码来手动认证用户,可以使用方便的check_password()函数。它接受两个必需参数:要检查的明文密码和要与数据库中的用户密码字段的完整值进行比较的值。如果它们匹配,则返回True,否则返回False。

它将像这样工作:<br>
views.py

from django.contrib.auth.hashers import check_password

[...]
plain_pw_from_post = form.cleaned_data.get(...)
hashed_pw_from_usermodel = User.objects.all().first().password

if check_password(plain_pw_from_post, hashed_pw_from_usermodel):
    # 在这里插入你的登录逻辑
else:
    # 登录失败的逻辑在这里
[...]

在OP分享了他的用户模型代码后进行编辑:

查看这个:Django的用户模型。很可能你希望从该模型继承你的自定义用户模型!这已经提供了许多功能。如你在链接中所见,它已经有了密码字段。如果你从中继承你的模型,你也可以很容易地利用authenticate函数,如你在你的问题的另一个回答中所描述的那样。

models.py

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    user_role_id = models.CharField(max_length=20)
    user_avatar_path = models.CharField(max_length=300)
    user_job_title = models.TextField(blank=True, null=True)
    user_educ_qual = models.TextField(blank=True, null=True)
    user_companies = models.TextField(blank=True, null=true)

由于我们已经从AbstractUser继承,所以可以替代电子邮件、用户名和密码字段。

views.py

from django.contrib.auth import authenticate

def user_login(request):
    if request.method == &quot;POST&quot;:
        posting_user = User.objects.get_or_404(username=request.POST[&#39;username&#39;])
        # if check_password(request.POST[&#39;password&#39;], posting_user.password):
          
        user = authenticate(username=posting_user.username, password=request.POST[&#39;password&#39;])
        if user is not None:
            return HttpResponseRedirect(&#39;/user_index&#39;)
        else:
            return render(request, &#39;EmpLogin.html&#39;, {&#39;msg&#39;: &quot;0&quot;})
    else:
        return render(request, &#39;EmpLogin.html&#39;)

阅读这个关于“普通”Django用户认证的文档。

英文:

Here you should find everything you need. You need a password field for your User, that should be clear.

> If you’d like to manually authenticate a user by comparing a
> plain-text password to the hashed password in the database, use the
> convenience function check_password(). It takes two mandatory
> arguments: the plain-text password to check, and the full value of a
> user’s password field in the database to check against. It returns
> True if they match, False otherwise.

It would work something like this: <br>
views.py

from django.contrib.auth.hashers import check_password

[...]
plain_pw_from_post = form.cleaned_data.get(...)
hashed_pw_from_usermodel = User.objects.all().first().password

if check_password(plain_pw_from_post, hashed_pw_from_usermodel):
    # insert your login logic here
else:
    # login failed logic here
[...]

Edit after OP shared the code for his user-model:

Check out this: Django's User model
Most likely you would want to inherit your custom user model from that model! That gives you a lot of functionality already. As you can see in the link it also already has a password. If you inherit your model from that you can also very easily utilize the authenticate function as described in another answer to your question.

models.py

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    user_role_id = models.CharField(max_length=20)
    user_avatar_path = models.CharField(max_length=300)
    user_job_title = models.TextField(blank=True, null=True)
    user_educ_qual = models.TextField(blank=True, null=True)
    user_companies = models.TextField(blank=True, null=True)

Replace email, username and password field since by inheriting from AbstractUser we already have those.

views.py

from django.contrib.auth import authenticate

def user_login(request):
    if request.method == &quot;POST&quot;:
        posting_user = User.objects.get_or_404(username=request.POST[&#39;username&#39;])
      #  if check_password(request.POST[&#39;password&#39;], posting_user.password):
          
        user = authenticate(username=posting_user.username, password=request.POST[&#39;password&#39;])
        if user is not None:
            return HttpResponseRedirect(&#39;/user_index&#39;)
        else:
            return render(request, &#39;EmpLogin.html&#39;, {&#39;msg&#39;: &quot;0&quot;})
    else:
        return render(request, &#39;EmpLogin.html&#39;)

Read this for "normal" django authentication of users.

答案2

得分: 1

请使用authenticate方法对用户进行身份验证。

from django.contrib.auth import authenticate

def user_login(request):
    if request.method == "POST":
        user_email = request.POST.get('user_email')
        user_password = request.POST.get('user_password')
        user_details = authenticate(request, email=user_email, password=user_password)

        if user_details is not None:
            request.session['logged_in'] = True
            request.session['user_email'] = user_details.email
            request.session['u_id'] = user_details.id
            request.session['user_name'] = user_details.username
            request.session['u_type'] = "emp"
            return HttpResponseRedirect('/user_index/')
        else:
            return render(request, 'EmpLogin.html', {'msg': "0"})
    else:
        return render(request, 'EmpLogin.html')
英文:

Please use the autenticate method to authenticate a user.

from django.contrib.auth import authenticate

def user_login(request):
   if request.method == &quot;POST&quot;:
    user_email = request.POST.get(&#39;user_email&#39;)
    user_password = request.POST.get(&#39;user_password&#39;)
    user_details = authenticate(request, email=user_email, password=user_password)
    
    if user_details is not None:
        request.session[&#39;logged_in&#39;] = True
        request.session[&#39;user_email&#39;] = user_details.email
        request.session[&#39;u_id&#39;] = user_details.id
        request.session[&#39;user_name&#39;] = user_details.username
        request.session[&#39;u_type&#39;] = &quot;emp&quot;
        return HttpResponseRedirect(&#39;/user_index/&#39;)
    else:
        return render(request, &#39;EmpLogin.html&#39;, {&#39;msg&#39;: &quot;0&quot;})
else:
    return render(request, &#39;EmpLogin.html&#39;)

答案3

得分: 0

修复了代码,最终它正在运行。我想分享一下:

def user_login(request):
    if request.method == "POST":
        user_email = request.POST['user_email']
        user_password = request.POST['user_password']
        user_details = User.objects.filter(user_email=user_email).values()
        hashed_pw = User.objects.all().first().user_password
        check_password(user_password, hashed_pw)

        if user_details:
            request.session['logged_in'] = True
            request.session['user_email'] = user_details[0]["user_email"]
            request.session['u_id'] = user_details[0]["user_email"]
            request.session['user_name'] = user_details[0]["user_name"]
            request.session['u_type'] = "emp"
            return HttpResponseRedirect('/user_index')
        else:
            return render(request, 'EmpLogin.html', {'msg': "0"})
    else:
        return render(request, 'EmpLogin.html')
英文:

fixed the code finally it's working I thought I'd share:

def user_login(request):
    if request.method == &quot;POST&quot;:
        user_email = request.POST[&#39;user_email&#39;]
        user_password = request.POST[&#39;user_password&#39;]
        user_details = User.objects.filter(user_email=user_email).values()
        hashed_pw = User.objects.all().first().user_password
        check_password(user_password, hashed_pw)

        if user_details:
            request.session[&#39;logged_in&#39;] = True
            request.session[&#39;user_email&#39;] = user_details[0][&quot;user_email&quot;]
            request.session[&#39;u_id&#39;] = user_details[0][&quot;user_email&quot;]
            request.session[&#39;user_name&#39;] = user_details[0][&quot;user_name&quot;]
            request.session[&#39;u_type&#39;] = &quot;emp&quot;
            return HttpResponseRedirect(&#39;/user_index&#39;)
        else:
            return render(request, &#39;EmpLogin.html&#39;, {&#39;msg&#39;: &quot;0&quot;})
    else:
        return render(request, &#39;EmpLogin.html&#39;)

huangapple
  • 本文由 发表于 2023年3月8日 16:29:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670785.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定