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的定义:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
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的定义:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
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)查询。
|
1
2
3
4
5
6
|
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的权限。
|
1
2
3
4
5
6
7
|
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方法。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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方法只是起代理的作用:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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结果集。
|
1
2
3
4
5
6
7
|
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。
|
1
2
3
4
|
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用来验证用户权限的。
|
1
2
3
4
5
6
7
8
9
10
|
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
|
本文详细介绍了Django框架中的Auth模块工作原理,包括认证流程、用户信息获取及权限管理等方面的内容。深入探讨了ModelBackend类中的核心方法,如authenticate、get_user以及各种权限查询方法。
1375

被折叠的 条评论
为什么被折叠?



