Django 中的 AbstractUser 未进行身份验证

AbstractUser in Django is not authenticating

Django 版本 3.2

我创建了一个 AbstractUser 模型来存储 Bank's Customer 的信息。我可以使用用户名和密码注册客户。但是它在登录时没有得到验证。 在管理页面中,密码被保存为纯文本,这不是预期的。在 Django 中应该默认以散列形式保存。 请给出一些指导来解决这个问题。我做错了什么?

在 settings.py 我添加了行: AUTH_USER_MODEL = 'banking.Customer'

models.py :

'''
    This stores all customers of this bank .
'''
class Customer(AbstractUser):
    #username   = models.CharField(max_length=128, unique=True)
    #first_name     = models.CharField(max_length=128)
    #last_name  = models.CharField(max_length=128)
    #email      = models.CharField(max_length=128)
    phone       = models.CharField(max_length=128)
    #password   = models.CharField(max_length=2048)
    dateJoined = models.DateTimeField(auto_now_add=True)

    # completed, pending, blocked, error
    verificationStatus = models.CharField(max_length=128)

    #USERNAME_FIELD = 'username'
    #REQUIRED_FIELDS = []

    def __str__(self):
        return f"{self.username}, {self.first_name} {self.last_name}, {self.email}, {self.password}"

views.py :

def register(request):
    if request.method == "POST":
        
        # get the information from form
        print("POST request :" + str(request.POST))
        userName = request.POST["userName"]
        firstName = request.POST["firstName"]
        lastName = request.POST["lastName"]
        email = request.POST["email"]
        phone = request.POST["phone"]
        password = request.POST["password"]

        # insert it in DB, keep in mind that username should be unique
        try:
            customer = Customer(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, password=password, verificationStatus="verified")
            customer.save()

            print("Database " + str(customer))
            return HttpResponseRedirect(reverse('login'))
        except:
            # send register page agin with error message
            context = {"message": userName + " userName is already taken ."}
            return render(request, "banking/register.html", context)
    else:
        return render(request, "banking/register.html")



def login(request):
    if request.method == "POST":
        # get info from login form
        username = request.POST["userName"]
        password = request.POST["password"]

        # check if user is valid
        customer = None
        try:
            # check if userName exist in DB
            print("check user")
            customer = authenticate(request, username=username, password=password)
        except:
            customer = None
        
        # save customer in session
        if customer is not None:
            login(request, customer)
            return HttpResponseRedirect(reverse('mainPage'))
        else:
            # return to login page with error message
            context = {"message": "Invalid credentials"}
            return render(request, "banking/login.html", context) 
    else:
        return render(request, "banking/login.html")

您使用模型 __init__ 方法(构造函数)创建客户:

customer = Customer(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, password=password, verificationStatus="verified")

但是这里没有考虑密码需要hashed,将密码保存为明文。这会导致您的用户无法登录,因为 authenticate 函数在密码经过哈希处理的前提下工作。

您应该改用用户模型管理器 UserManagercreate_user [Django docs] 方法,它会自动散列密码:

customer = Customer.objects.create_user(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, password=password, verificationStatus="verified")

在 Django 中创建自定义 User class 时,密码加密和保存机制应由管理器处理 class。
请参阅 EmployeeManager class in the astikgabani/Inventory-Management 存储库中使用的代码。

register() 方法 views.py 中,您必须将代码编辑为:

customer = Customer(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, verificationStatus="verified")
customer.set_password(password)
customer.save()

保存用户时,我们必须使用set_password()方法设置密码,因为它将使用适当的hash/encryption算法保存密码。