django.contrib.auth.backend-后台

backend.py文件目前有两个类,ModelBackend和RemoteUserBackend。

首先看ModelBackend的对外接口,

认证方面: authenticate

获取用户: get_user, 

权限方面: get_user_permissions, get_group_permissions,get_all_permissions,has_perm, has_module_perms


认证方面:

首先看authenticate的定义:

def authenticate(self, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        try:
            user = UserModel._default_manager.get_by_natural_key(username)
            if user.check_password(password):
                return user
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a non-existing user (#20760).
            UserModel().set_password(password)

它首先调用get_user_model方法,获取User模型。之所以要封装在一个单独的方法里,是为了做到User模型自定义。

下面是get_user_model的定义:

def get_user_model():
    """
    Returns the User model that is active in this project.
    """
    try:
        return django_apps.get_model(settings.AUTH_USER_MODEL)
    except ValueError:
        raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form 'app_label.model_name'")
    except LookupError:
        raise ImproperlyConfigured(
            "AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL
        )

可以看到这个返回的User模型是由配置文件的AUTH_USER_MODEL属性指定的。可以查看django.conf.global_settings (django的默认配置),AUTH_USER_MODEL的值为'auth.User'。

看完get_user_model函数,再接着看authenticate方法。注意看它会获取kwargs的UserModel.USERNAME_FIELD属性,这是User模型的标识字段,以auth中的User模型为例,它的标识字段就是username,然后User模型的objects会根据此标识字段,调用get_by_natural_key方法查询user。关于User模型这一块,下篇会详细介绍。

authenticate的认证任务最后是交给user的check_password执行了。


获取用户:

然后看获取用户方面,get_user不同于上面的查询,它是根据pk(即为id)查询。

def get_user(self, user_id):
        UserModel = get_user_model()
        try:
            return UserModel._default_manager.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None


权限方面:

权限的查询,需要对auth的models有所了解。简单的说一下models的结构:

Permission是表示权限的model,

Group是表示组的model,

User是表示用户的model。


Permission与Group是多对多的关系,通过Group的字段(permission)指定。

User与Group是多对多的关系,通过User的字段(group)指定。

User与Permission是多对多的关系,通过User的字段(user_permissions)指定。


关于权限方面的方法,实质上就是数据库的查询。这里涉及到User的权限和Group的权限。

def _get_user_permissions(self, user_obj):
    return user_obj.user_permissions.all()

def _get_group_permissions(self, user_obj):
    user_groups_field = get_user_model()._meta.get_field('groups')
    user_groups_query = 'group__%s' % user_groups_field.related_query_name()
    return Permission.objects.filter(**{user_groups_query: user_obj})

_get_group_permissions是根据用户所属的组,查询组的权限。

这里model用的查询api,涉及到双下划线的使用。上面首先会去获取User和Group关联的字段,然后获取related_query_name,最后联合查询得到权限。


get_user_permissions和get_group_permissions只是调用了_get_permissions方法。

def get_user_permissions(self, user_obj, obj=None):
        """
        Returns a set of permission strings the user `user_obj` has from their
        `user_permissions`.
        """
        return self._get_permissions(user_obj, obj, 'user')

    def get_group_permissions(self, user_obj, obj=None):
        """
        Returns a set of permission strings the user `user_obj` has from the
        groups they belong.
        """
        return self._get_permissions(user_obj, obj, 'group')


_get_permissions方法只是起代理的作用:

def _get_permissions(self, user_obj, obj, from_name):
        """
        Returns the permissions of `user_obj` from `from_name`. `from_name` can
        be either "group" or "user" to return permissions from
        `_get_group_permissions` or `_get_user_permissions` respectively.
        """
        if not user_obj.is_active or user_obj.is_anonymous() or obj is not None:
            return set()

        perm_cache_name = '_%s_perm_cache' % from_name
        if not hasattr(user_obj, perm_cache_name):
            if user_obj.is_superuser:
                perms = Permission.objects.all()
            else:
                perms = getattr(self, '_get_%s_permissions' % from_name)(user_obj)
            perms = perms.values_list('content_type__app_label', 'codename').order_by()
            setattr(user_obj, perm_cache_name, set("%s.%s" % (ct, name) for ct, name in perms))
        return getattr(user_obj, perm_cache_name)


它最终会调用_get_user_permissions和_get_group_permissions方法返回结果。其中也在user_obj中存储了对应的缓存。

注意它将返回Permission对象,取出app_label(content_type为外键),和codename属性,并且通过点连接, 返回set结果集。


def get_all_permissions(self, user_obj, obj=None):
        if not user_obj.is_active or user_obj.is_anonymous() or obj is not None:
            return set()
        if not hasattr(user_obj, '_perm_cache'):
            user_obj._perm_cache = self.get_user_permissions(user_obj)
            user_obj._perm_cache.update(self.get_group_permissions(user_obj))
        return user_obj._perm_cache

get_all_permissions也只是组合了user和group对应的permission。


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)

has_perm用来验证用户权限的。


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

这里它会去验证返回的结果集,是有否相应app_label开头。

转载于:https://my.oschina.net/u/569730/blog/370222

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值