簡體   English   中英

自定義用戶模型和自定義身份驗證在Django中不起作用。 身份驗證表單未通過驗證測試

[英]Custom user model and custom authentication not working in django. Authentication form is not passing validation tests

我正在嘗試為我的應用程序實現自定義用戶模型和自定義身份驗證。
我能夠創建模型並進行遷移。 但是,當我創建表單並實現登錄模板時,出現此錯誤-

login
User model with this Login already exists.

查看我在哪里對用戶進行身份驗證-

from django.shortcuts import render_to_response, redirect, render
from django.template import RequestContext
from django.contrib.auth import login, logout , authenticate
from accounts.forms import AuthenticationForm
from django.contrib.auth.decorators import login_required
def accounts_login(request):
    context = {}
    if request.method == "POST":
        form = AuthenticationForm(request.POST) #getting error here
        print(form)
        if form.is_valid():
        user = authenticate(login = request.POST["login"], password = request.POST["password"])
        if user is not None:
            print(user)
            login(request,user)
            next_url = request.POST["next"]
            return redirect(next_url, args=(), kwargs={})
        #more code - not required here. Let me know if needed.

認證表格:

from django import forms
from accounts.models import UserModel

class AuthenticationForm(forms.Form):
    login = forms.CharField(max_length=128, required=True)
    password = forms.CharField(max_length=128, required=True)

我的自定義用戶模型和用戶管理器-

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.utils import timezone
from django.db.models import Max

class MyUserManager(BaseUserManager):
    use_in_migrations = True
    def create_user(self,login, parent_type, last_name, first_name, password):
        return create_superuser(self,login, parent_type, last_name, first_name, password)


    def create_superuser(self,login, parent_type, last_name, first_name, password):
        maxx = self.model.objects.all().aggregate(Max('sys_id'))
        print(maxx)
        user = self.model(
                          sys_id = maxx["sys_id__max"] + 1,
                          login = login,
                          password = password,
                          parent_type = parent_type,
                          last_name = last_name,
                          first_name = first_name,
                          display_name = last_name + " " + first_name,
                          created_when = timezone.now()
                          )
        user.save(using=self._db)
        # no difference here...actually can set is_admin = True or something like that.
        return user

class UserModel(AbstractBaseUser):
    # custom user class
    SYSTEM = 0
    TENANT = 1
    parent_type_choices = (
                           (SYSTEM, 'System'),
                           (TENANT, 'Tenant')
                           )
    sys_id = models.BigIntegerField(primary_key=True, blank=True)
    parent_type = models.PositiveIntegerField(choices=parent_type_choices, null=False, blank=False)
    parent_sys_id = models.ForeignKey('tenant.TenantModel', on_delete = models.SET_NULL, null=True, blank=True)
    last_name = models.CharField(null=False, blank=False, max_length=40)
    first_name = models.CharField(max_length=40, null=False, blank=False)
    display_name = models.CharField(max_length=80, unique=True, null=False, blank=True)
    login = models.CharField(max_length=40, unique=True, null=False, blank=False)
    authentication_method = models.CharField(max_length=80, null=True, blank=True)
    access_valid_start = models.DateTimeField(null=True, blank=True)
    access_valid_end = models.DateTimeField(null=True, blank=True)
    created_when = models.DateTimeField(null=True, blank=True, )
    created_by = models.BigIntegerField(null=True, blank=True)
    last_updated_when = models.DateTimeField(null=True, blank=True)
    last_updated_by = models.BigIntegerField(null=True, blank=True)
    notes = models.CharField(max_length=2048, null=True, blank=True)
    is_active = models.BooleanField(default=True)

    objects = MyUserManager()

    USERNAME_FIELD = "login"
    # REQUIRED_FIELDS must contain all required fields on your User model, 
    # but should not contain the USERNAME_FIELD or password as these fields will always be prompted for.
    REQUIRED_FIELDS = ['parent_type', 'last_name', 'first_name']

    class Meta:
        app_label = "accounts"
        db_table = "Users"

    def __str__(self):
        return self.display_name

    def get_full_name(self):
        return self.display_name

    def get_short_name(self):
        return self.last_name

    def check_password(self,password):
        return True
        if self.password ==password:
            return true

自定義后端

from django.conf import settings
from accounts.models import UserModel

class MyAuthBackend(object):
    def authenticate(self, login, password):
        try:
            user = UserModel.objects.get(login=login)
            if user.check_password(password):
                return user
            else:
                print("wrong password")
                return None
        except User.DoesNotExist:
            return None
        except Exception as e:
            print(repr(e))
            return None

    def get_user(self, user_id):
        try:
            user = User.objects.get(pk=user_id)
            if user.is_active:
                return user
            return None
        except User.DoesNotExist:
            return None

在setting.py中添加了這兩個變量

AUTH_USER_MODEL = 'accounts.UserModel'
AUTHENTICATION_BACKENDS = ('accounts.backends.MyAuthBackend',)

從命令行獲取后端

>>> get_backends()
[<accounts.backends.MyAuthBackend object at 0x7f2c438afe80>]

具有用戶名的用戶說db中存在xyz和密碼“ ABC”。
1.當我嘗試使用現有的用戶名和密碼登錄時,會拋出錯誤。 User model with this Login already exists.名的User model with this Login already exists.
2.當我嘗試使用不存在的用戶名和密碼(讓我們說xyz123)登錄時,拋出錯誤error authenticate() takes 0 positional arguments but 2 were given

我關注了多篇文章,但主要是django官方文檔。 閱讀多篇文章以解決問題,但失敗了。
請提出我在做什么錯。

更新1:將AuthenticationForm從ModelForm更改為普通Form類。 錯誤1已解決。
更新2:不使用Daniel指出的自定義后端,它沒有用,因為我沒有在其中做任何新的事情。 因此,錯誤2也得以解決。
更新3:現在在創建超級用戶功能中將用戶保存到數據庫之前對密碼進行哈希處理。 user.set_password(password)

首先,您將密碼以純文本格式存儲在覆蓋的create_superuser方法中。 絕對不能這樣做 除了安全性問題外,它實際上不會起作用,因為身份驗證后端會在將提交的密碼與保存的版本進行比較之前對提交的密碼進行哈希處理,因此它永遠不會匹配。

其次,您的實際問題是您的AuthenticationForm是ModelForm。 這樣,它將嘗試查看是否可以使用該電子郵件和密碼創建用戶。 沒有理由使其成為模型形式,您應該只使用帶有CharFields的簡單形式來獲取電子郵件和密碼。

請注意,在解決了純文本密碼問題之前,您實際上將無法登錄。 還請注意,您的自定義auth后端-以及不符合docs中描述的接口而破壞了authenticate方法-不會執行內置操作無法執行的任何操作; 它沒有意義,應該將其刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM