django.contrib.auth.backend-后台

本文详细介绍了Django框架中的Auth模块工作原理,包括认证流程、用户信息获取及权限管理等方面的内容。深入探讨了ModelBackend类中的核心方法,如authenticate、get_user以及各种权限查询方法。

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
这里它会去验证返回的结果集,是有否相应app_label开头。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值