django 自定义user使用权限管理模块

这篇文章主要是讲如何让自定义的user模块也能用到django.contrib.auth中的权限管理模块


看这篇文章之前请先看一下我前边的两篇文章,本文以这两篇文章为基础:

django 自定义 USER

用源码告诉你django权限管理是怎么回事


下边是一个大概的实现,后边再做详细分析:

1、user model自定义

class AbstractUser(models.Model):
    # 登录信息
    id = models.AutoField(primary_key=True)
    staff = models.IntegerField(default=0, verbose_name=u'员工号')
    ename = models.CharField(max_length=30, null=False, blank=False, unique=True, verbose_name=u'英文名')
    cname = models.CharField(max_length=30, null=False, blank=True, verbose_name=u'中文名')
    deptid = models.IntegerField(default=0, verbose_name=u'部门ID')
    deptname = models.CharField(max_length=255, db_index=True, verbose_name=u'部门名')
    expiration = models.DateTimeField(null=True)
    last_login = models.DateTimeField(default=timezone.now)

    is_staff = True
    is_active = True


    USERNAME_FIELD = 'ename'
    REQUIRED_FIELDS = []

    class Meta:
        verbose_name = 'user'
        verbose_name_plural = 'users'
        abstract = True

    def get_full_name(self):
        return u'%s(%s)' % (self.ename, self.cname)

    def get_short_name(self):
        return self.ename

    def get_username(self):
        return self.get_full_name()

    def __uincode__(self):
        return self.get_full_name()

    def is_anonymous(self):
        return False

    def is_authenticated(self):
        return True


class User(AbstractUser, PermissionsMixin):
    # 组织架构信息
    team_id = models.IntegerField(default=0, db_index=True, help_text=u'员工组织架构(id)', null=True)
    team_full_id = models.CharField(max_length=255, db_index=True, help_text=u'员工组织架构(路径)', null=True)

    # # 权限组信息
    # groups = models.ManyToManyField(Group, help_text=u'员工所属用户组')

    class Meta:
        db_table = 'user'

    def has_group(self, group):
        if not self.is_active:
            return False
        if self.is_superuser:
            return True
        if not hasattr(self, '_group_cache'):
            self._group_cache = set([g.name for g in self.groups.all()])
        return group in self._group_cache

    def __unicode__(self):
        return u'%s(%s)' % (self.ename, self.cname)
记得到setting中设置AUTH_USER_MODEL 为自定义user类
2、添加自己的backend类:

class TicketBackend(object):

    def __init__(self):
        from soap import client
        self.passport = client.passport

    def authenticate(self, ticket=None):
        '''
        授权函数
        '''
        if ticket:
            User = get_user_model()
            data = self.passport.DecryptTicket(ticket)
            if not hasattr(data, 'LoginName'):
                return None
            #判断权限
            if not AuthenticateJudge.hasAuthenticate(data.LoginName):
                return None
            if data:
                ename = unicode(data.LoginName)
                try:
                    user = User.objects.get(ename=ename)
                except User.DoesNotExist:
                    user = User()
                user.is_active = True
                user.update(data)
                user.save()
                return user

        return None
    
    def get_user(self, user_id):
        User = get_user_model()
        try:
            return User.objects.get(id=user_id)
        except User.DoesNotExist:
            return None

    def get_group_permissions(self, user_obj, obj=None):
        """
        Returns a set of permission strings that this user has through his/her
        groups.
        """
        if user_obj.is_anonymous() or obj is not None:
            return set()
        if not hasattr(user_obj, '_group_perm_cache'):
            if user_obj.is_superuser:
                perms = Permission.objects.all()
            else:
                user_groups_field = get_user_model()._meta.get_field('groups')
                user_groups_query = 'group__%s' % user_groups_field.related_query_name()
                perms = Permission.objects.filter(**{user_groups_query: user_obj})
            perms = perms.values_list('content_type__app_label', 'codename').order_by()
            user_obj._group_perm_cache = set(["%s.%s" % (ct, name) for ct, name in perms])
        return user_obj._group_perm_cache

    def get_all_permissions(self, user_obj, obj=None):
        if user_obj.is_anonymous() or obj is not None:
            return set()
        if not hasattr(user_obj, '_perm_cache'):
            user_obj._perm_cache = set(["%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related()])
            user_obj._perm_cache.update(self.get_group_permissions(user_obj))
        return user_obj._perm_cache

    def has_perm(self, user_obj, perm, obj=None):
        if not user_obj.is_active:
            return False
        return perm in self.get_all_permissions(user_obj, obj)

    def has_module_perms(self, user_obj, app_label):
        """
        Returns True if user_obj has any permissions in the given app_label.
        """
        if not user_obj.is_active:
            return False
        for perm in self.get_all_permissions(user_obj):
            if perm[:perm.index('.')] == app_label:
                return True
        return False

3、修改settings.py中的AUTHENTICATION_BACKENDS,将授权、权限判断入口设为我们自己的backend类(其实这里可以有多个backend类共存,但是考虑到有些属性、函数对象可能在其他backend不存在而导致异常,所以注释掉系统默认的ModelBackend):

AUTHENTICATION_BACKENDS = [
    # 自己的权限判断方法
    'users.backend.TicketBackend',
    #系统的权限判断方法
    # 'django.contrib.auth.backends.ModelBackend',
    ]


解析:

从《用源码告诉你django权限管理是怎么回事》中我们可以获知,不管是修饰符permission_required 还是 user_passes_test 都是通过调用user.has_perm函数进行权限验证的。为了支持这个接口,我们在自定义自己的AUTH_USER_MODEL类时,我们必须继承 PermissionsMixin 类,这样我们才能使用PermissionsMixin类中提供的函数,包括has_perm,从PermissionMixin的定义我们可以看到,继承了PermissionsMixin类就自动添加了groups、user_permissions属性,这些是使用PermissionsMixin中权限相关的函数所必须的

class PermissionsMixin(models.Model):
    """
    A mixin class that adds the fields and methods necessary to support
    Django's Group and Permission model using the ModelBackend.
    """
    is_superuser = models.BooleanField(_('superuser status'), default=False,
        help_text=_('Designates that this user has all permissions without '
                    'explicitly assigning them.'))
    groups = models.ManyToManyField(Group, verbose_name=_('groups'),
        blank=True, help_text=_('The groups this user belongs to. A user will '
                                'get all permissions granted to each of '
                                'his/her group.'),
        related_name="user_set", related_query_name="user")
    user_permissions = models.ManyToManyField(Permission,
        verbose_name=_('user permissions'), blank=True,
        help_text=_('Specific permissions for this user.'),
        related_name="user_set", related_query_name="user")


怎么将我们自己的has_perm函数设定为默认user.has_perm函数呢?

从《用源码告诉你django权限管理是怎么回事》中我们也可以看到通过调用系统的user.has_perm函数从settings.py中的AUTHENTICATION_BACKENDS 中找到相应的backend类,并调用其中的has_perm函数,所以我们需要编写我们自己的backend类,并注册到AUTHENTICATION_BACKENDS 中,这样下来我们就可以通过user.has_perm对我们自定义的user类进行权限验证、授权了。也可以直接调用修饰符:user_passes_test、permission_required。




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值