backend.py文件目前有兩個類,ModelBackend和RemoteUserBackend。python
首先看ModelBackend的對外接口,數據庫
認證方面: authenticatedjango
獲取用戶: get_user, api
權限方面: get_user_permissions, get_group_permissions,get_all_permissions,has_perm, has_module_perms緩存
認證方面:app
首先看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模型自定義。this
下面是get_user_model的定義:spa
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開頭。