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开头。