Django无法认证或密码散列错误

k4aesqcs  于 2022-12-20  发布在  Go
关注(0)|答案(1)|浏览(77)

我使用自定义用户模型,这样我就可以使用电子邮件而不是用户名进行身份验证。

from django.db import models
from django.contrib.auth.models import (
    AbstractBaseUser,
    BaseUserManager,
    PermissionsMixin,
)

class UserManager(BaseUserManager):
    def create_user(
        self,
        email,
        password,
        confirm_code=None,
        username=None,
        role=None,
    ):
        user = self.model(email=self.normalize_email(email))
        user.set_password(password)
        user.confirm_code = confirm_code
        user.save()
        return user

    def create_superuser(self, email, password, role, username=None):
        user = self.model(email=self.normalize_email(email))
        user.set_password(password)
        user.role = role
        user.is_staff = True
        user.is_active = True
        user.is_superuser = True
        user.save()
        return user

class User(AbstractBaseUser, PermissionsMixin):
    EM = "EM"
    SM = "SM"
    DH = "DH"
    ST = "ST"
    ROLES = [
        (EM, "Executive Management"),
        (SM, "Senior Management"),
        (DH, "Department Head"),
        (ST, "Staff Member"),
    ]

    objects = UserManager()
    role = models.CharField(max_length=2, choices=ROLES, default=US, blank=True)
    username = models.CharField(max_length=20, unique=True, blank=True, null=True)
    email = models.EmailField(max_length=255, unique=True)
    slug = models.SlugField(blank=True, null=True)
    confirm_code = models.CharField(max_length=20, null=True, blank=True)
    is_active = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    has_profile = models.BooleanField(default=False)
    email_verified_at = models.DateTimeField(auto_now=False, null=True, blank=True)
    code = models.CharField(max_length=8, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created at")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="Updated at")

    class Meta:
        verbose_name = "User"
        verbose_name_plural = "Users"
        ordering = ["username"]
        db_table = "users"

    def get_absolute_url(self):
        return f"{self.slug}"

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["role"]

当我注册一个用户时,用户在数据库中被正确地创建,密码被散列我假设是正确的,因为我看到的是散列而不是原始密码。下面是我用来注册用户的方法:

@api_view(["POST"])
def RegisterUser(request, *args, **kwargs):
    code = []
    numbers = range(7)
    for num in numbers:
        code.append(randint(0, 9))

    email = request.data["email"]
    confirmemail = request.data["confirmemail"]
    password = request.data["password"]
    confirmpassword = request.data["confirmpassword"]
    errors = []
    if email != confirmemail:
        errors.append("emailmatch")
        return Response("Emails do not match", status=500)
    if confirmpassword != password:
        errors.append("passmatch")
        return Response("Password do not match", status=500)
    if User.objects.filter(email=email):
        errors.append("emailexists")
        return Response("User is already registered", status=500)
    else:
        pass
    if len(errors) > 0:
        return Response(False)
    else:
        password_to_save = make_password(password)
        confirm_code = "".join(str(e) for e in code)
        user = User.objects.create_user(
            email=email, password=password_to_save, confirm_code=confirm_code
        )
        token = Token.objects.create(user=user)
        from_email = "info@website.com"
        link = f"http://127.0.0.1:8000/api/v1/users/confirm/{user.id}/{token}/"
        context = {"link": link, "code": code}
        template = get_template("emails/welcome.html").render(context)

        subject = "Successfully registered"
        message = "Welcome to website"

        try:
            send_mail(
                subject,
                message=message,
                from_email=from_email,
                recipient_list=[email],
                html_message=template,
            )
        except:
            return Response("Could not send mail")

        serializer = RegisterSerializer(user)

        return Response(serializer.data)

我有一个自定义的后端来验证用户使用电子邮件而不是用户名,这里是:

class EmailBackend(ModelBackend):
    def authenticate(self, request, **kwargs):
        email = kwargs.get("email", None)
        user = User.objects.get(email=email)
        if user:
            breakpoint()
            if user.check_password(kwargs.get("password", None)):
                return user
            else:
                return None
        else:
            User.DoesNotExist
        return None

它就是不工作,我无法登录。用户是活动的!如果我执行一个breakpoint(),如这里所示,我通过在user. check_password('password ')中输入原始密码来手动检查密码,那么它返回false。那么check_password不是应该对输入的原始密码进行散列,并将散列与数据库中的散列进行比较吗?
这是可行的:

password = "hello"
saved = make_password(password)
true = check_password(password, saved)

那么,为什么它不能在我的身份验证后端,这是完全相同的工作?
我需要使用另一个散列算法还是什么?
那么我应该做些什么,如何验证用户?是否有其他方法可以比较用户在表单中输入的密码和保存在数据库中的散列密码?

uinbv5nw

uinbv5nw1#

您正在管理器中使用create_user中的set_password函数。此方法本身调用make_password函数。
因此,当您将通过make_password生成的散列密码传递给create_user时,该散列密码将在set_password函数中再次进行散列。
所以不需要自己调用make_password,只需要将普通密码传递给create_user方法即可。

相关问题