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

来源:互联网 发布:mac希腊字母怎么打 编辑:程序博客网 时间:2024/05/14 13:10

这篇文章主要是讲如何让自定义的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 Trueclass 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 0
原创粉丝点击