无法在Django中使用自定义身份验证后端

时间:2017-03-27 19:00:09

标签: django

我使用AbstractBaseUser类创建了一个自定义用户模型。这里的代码就在这里。

class UserModel(AbstractBaseUser):
    user_type_choices = (
                            (constants.USER_TYPE_ADMIN, 'Admin'),
                            (constants.USER_TYPE_INSTITUTE, 'Institute'),
                            (constants.USER_TYPE_STUDENT, 'Student')
                        )
    sys_id = models.AutoField(primary_key=True, blank=True)        
    name = models.CharField(max_length=127, null=False, blank=False)    
    email = models.EmailField(max_length=127, unique=True, null=False, blank=False)
    mobile = models.CharField(max_length=10, unique=True, null=False, blank=False)  
    user_type = models.PositiveSmallIntegerField(choices=user_type_choices, null=False, blank=True, help_text="Admin(1)/Institute(2)/Student(3)")  
    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)
    is_staff = models.BooleanField(default=True)

    objects = MyUserManager()

    USERNAME_FIELD = "email"
    # 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 = ['name', 'mobile', 'user_type']

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

    def __str__(self):
        return self.email

    def get_full_name(self):
        return self.name

    def get_short_name(self):
        return self.name

    def is_access_valid(self):
        if self.access_valid_end > utility.now():
            return True
        else:
            return False


    def save(self, *args, **kwargs):    
        if not self.sys_id:
            self.created_when = utility.now()
        self.last_updated_when = utility.now()
        return super(UserModel, self).save(*args, **kwargs)

其经理的代码如下。

class MyUserManager(BaseUserManager):
    use_in_migrations = True
    def create_user(self, email, name, mobile, user_type, password):      
        return create_superuser(self, email, name, mobile, user_type, password)

    # python manage.py createsuperuser
    def create_superuser(self, email, name, mobile, user_type, password):
        user = self.model(
                          email = email,
                          name = name,
                          mobile = mobile,
                          user_type = user_type,
                          access_valid_start = utility.now(),
                          access_valid_end = utility.get_access_end_date(),
                          created_when = utility.now(),
                          created_by = constants.COMMAND_LINE_USER_ID, 
                          last_updated_when = utility.now(),
                          last_updated_by = constants.COMMAND_LINE_USER_ID,
                          notes = 'This user is created from command line. createsuperuser utility.'
                          )
        user.set_password(password)
        user.save(using=self._db)
        return user

我还创建了身份验证后端。

class MyAuthBackend(object):
    def authenticate(self, email, password):
        try:
            user = UserModel.objects.get(email=email)
            if user.check_password(password):
                return user
            else:
                return None
        except UserModel.DoesNotExist:
            logging.getLogger("error_logger").error("user with login %s does not exists " % login)
            return None
        except Exception as e:
            logging.getLogger("error_logger").error("user with login %s does not exists " % login)
            return None

    def get_user(self, user_id):
        # user_id must be the primary key of table.
        try:
            user = UserModel.objects.get(sys_id=user_id)
            if user.is_active:
                return user
            return None
        except UserModel.DoesNotExist:
            logging.getLogger("error_logger").error("user with %(user_id)d not found")
            return None

我在设置文件中包含了自定义用户模型和后端。

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

我从命令行创建了一个超级用户,但是当我尝试从admin登录URL登录时,抛出了以下错误。

Please enter the correct email and password for a staff account. Note that both fields may be case-sensitive.

根据this SO answer中的建议,我使用了后备身份验证后端,然后它开始抛出此错误:'UserModel' object has no attribute 'has_module_perms'。这意味着后备后端在这里工作。但它需要在自定义用户模型中添加以下功能。

def has_perm(self, perm, obj=None):
        return self.is_superuser

    # this methods are require to login super user from admin panel
    def has_module_perms(self, app_label):
        return self.is_superuser

并添加了is_superuser字段。现在工作正常。

所以我有以下问题:

  1. 为什么我在尝试从管理面板登录时无法使用自定义后端对用户进行身份验证?
  2. 为什么函数has_perm,is_staffis_superuser字段对于从管理面板登录是必需的?
  3. 为什么从我自己的登录表单登录时不需要has_perm函数,is_staff和is_superuser字段?

1 个答案:

答案 0 :(得分:0)

  1. 您进行了身份验证,但未获得授权。 Django Admin正在使用is_staff标志来授权您,如文档

  2. 中所述
  3. 它们是Django简单权限系统的一部分,Django管理员默认使用它,如documentation中所述

  4. 您没有使用权限系统,否则他们将成为权限系统的一部分。