Django:非员工用户可以登录管理页面

6

Python 3.5.1和Django 1.9

我在我的项目中创建了一个自定义用户模型:

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


class UserManager(BaseUserManager):
    def create_user(self, username, password=None):
        user = self.model(
            username=username,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, password):
        user = self.create_user(
            username,
            password=password,
        )

        user.is_admin = True
        user.is_superuser = True
        user.save(using=self._db)
        return user


# Users
class User(AbstractBaseUser):
    username = models.CharField(
        unique=True,
        max_length=50,
    )
    bio = models.TextField()

    is_active = models.BooleanField(default=True,
                                    verbose_name="Active",
                                    help_text="lorem")
    is_admin = models.BooleanField(default=False,
                                   verbose_name="Staff status",
                                   help_text="lorem")
    is_superuser = models.BooleanField(default=False,
                                       verbose_name="Superuser status",
                                       help_text="lorem")

    objects = UserManager()

    USERNAME_FIELD = 'username'

    def get_full_name(self):
        return self.username

    def get_short_name(self):
        return self.username

    def is_staff(self):
        return self.is_admin

    def __str__(self):
        return self.username

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

    def has_module_perms(self, db):
        return True

我按照官方文档这里的指导进行了操作。
我已经在settings.py中定义了AUTH_USER_MODEL。
自定义用户模型似乎一切正常,除了...
任何用户都可以登录到管理界面。当然,这并不是一个好事情。
以下是非管理员用户登录时管理界面的截图:non-admin login 以下是实际管理员用户登录时管理界面的截图:admin login 请注意右上角。使用非管理员用户登录时,菜单不会出现。奇怪。
管理员和非管理员用户都可以完全访问管理界面,他们都可以添加、修改和删除条目。
显然,这是一个可怕的安全问题,我甚至不知道从哪里开始调试。
2个回答

9

您需要将 is_staff 变成一个属性。如果使用内置的 User 模型,Django 期望它是一个模型字段,这意味着所有检查员工状态的操作都会发生在 if user.is_staff:,而不是 if user.is_staff():。您所需要做的就是在 is_staff 方法定义之前加上一行代码:

@property
def is_staff(self):
    return self.is_admin

由于Python在布尔上下文中将每个函数对象视为True,因此所有用户都通过了is_staff的检查。

如果您想知道为什么管理员在“STAFF STATUS”列中显示正确的值,那是因为is_staff在用户模型的默认ModelAdminlist_display中列出,并且ModelAdmin会检查list_display中的项是否可调用,如果是,则调用它们。但是,这只是为了显示值(因为list_display是一种更通用的机制),而不是进行任何实际的访问控制检查。


这个已经起作用了,非常感谢。也谢谢你描述发生了什么而不仅仅是一个答案 :) - 99lives

1

你需要继承AbstractBaseUserPermissionsMixin

如果你的用户类只是增加了一个"bio"字段,那么可能只需要从AbstractUser继承而不是AbstractBaseUser。AbstractUser已经包含了大部分重要内容,你可以在那里添加你的"bio"字段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接