rest-framework认证组件

      认证组件     

 

在执行APIView时的操作流程:

1.执行dispatch

在执行APIView中的dispatch方法时,在执行handler函数之前,会执行
self.initial(request, *args, **kwargs),此函数的功能有:
1.版本处理
2.用户认证
3.权限
4.访问频率限制

2.执行self.initial(request, *args, **kwargs)

def initial(self, request, *args, **kwargs):
    #设置响应器
     neg = self.perform_content_negotiation(request)
    #1.处理版本信息
    version, scheme = self.determine_version(request, *args, **kwargs)
    request.version, request.versioning_scheme = version, scheme
    #2.认证
    self.perform_authentication(request)
    #3.权限
    self.check_permissions(request)
    #4.请求用户进行访问频率的限制
    self.check_throttles(request)

3.执行self.perform_authentication(request)

def perform_authentication(self, request):
     request.user
self.perform_authentication(request)的值就是request.user的值

1.执行request.user,需要知道request是什么,request是封装后的request,返回dispatch中找到这个request

 def dispatch(self, request, *args, **kwargs):
         request = self.initialize_request(request, *args, **kwargs)

2.找到initialize_request函数,initialize_request返回Request的实例对象

def initialize_request(self, request, *args, **kwargs):
        parser_context = self.get_parser_context(request)
            return Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )

3.那么request就是Request的对象,执行request.user就是调用Request类中的user方法

request.user=Response().user

4.找到Request类,找到uesr方法

class Request(object):
         def __init__(self, request, parsers=None, authenticators=None,
                     negotiator=None, parser_context=None):
            self._request = request
            self.parsers = parsers or ()
            self.authenticators = authenticators or ()
         @property
         def user(self):
            if not hasattr(self, '_user'):
                with wrap_attributeerrors():
                    self._authenticate()
            return self._user
在uesr方法中,执行_authenticate函数,此时的self是request对象,不是当前类
因此在Request类找到_authenticate方法。
request.user=self._authenticate()

  1.执行_authenticate方法:

def _authenticate(self):
                for authenticator in self.authenticators:
                try:
                    user_auth_tuple = authenticator.authenticate(self)
                except exceptions.APIException:
                    self._not_authenticated()
                    raise
                if user_auth_tuple is not None:
                    self._authenticator = authenticator
                    self.user, self.auth = user_auth_tuple
                    return
循环self.authenticators,查找authenticators函数
 class Request(object):
            def __init__(self, request, parsers=None, authenticators=None,
                         negotiator=None, parser_context=None):
                self.authenticators = authenticators or ()

2.self.authenticators = authenticators or ()

 self.authenticators就是Request实例化时的参数authenticators
        Request(
                    request,
                    parsers=self.get_parsers(),
                    authenticators=self.get_authenticators(),
                    negotiator=self.get_content_negotiator(),
                    parser_context=parser_context
                )
        找到self.get_authenticators(),此时的self是当前类对象
找到self.get_authenticators(),此时的self是当前类对象

3.authenticators=self.get_authenticators(),

def get_authenticators(self):
            return [auth() for auth in self.authentication_classes]

4.self.get_authenticators()=[],找到self.authentication_classes的值

从当前类中查找authentication_classes属性,如果在当前类中我们定义了authentication_classes
就用我们定义的,如果当前类未定义就去父类中查找。因此我们在类中定义这个变量时值要设为可变类型

1.当前类中定义:

class AuthorModelView(ModelViewSet):
authentication_classes = [AuthUser]
循环这个列表,进行实例化,此时authenticators的值为[AuthUser(),]

2.当前类中未定义authentication_classes时,去父类中查找,在APIView中找到authentication_classes

 class APIView(View):
                authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
1.去api_settings中找DEFAULT_AUTHENTICATION_CLASSES属性:
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
api_settings是 APISettings的对象,去类中调用DEFAULT_AUTHENTICATION_CLASSES属性
2.class APISettings(object):
class APISettings(object):
                     def __init__(self, user_settings=None, defaults=None, import_strings=None):
                        if user_settings:
                            self._user_settings = self.__check_user_settings(user_settings)
                        self.defaults = defaults or DEFAULTS
                     def __getattr__(self, attr):
                        if attr not in self.defaults:
                            raise AttributeError("Invalid API setting: '%s'" % attr)
                        try:
                            val = self.user_settings[attr]
                        except KeyError:
                            val = self.defaults[attr]
在 APISettings中并没有DEFAULT_AUTHENTICATION_CLASSES属性,因此执行__getattr__方法
attr的值为DEFAULT_AUTHENTICATION_CLASSES
3.执行__getattr__
找到self.defaults的值,在APISettings实例化时 defaults的值为DEFAULTS,在init中self.defaults=DEFAULTS
 DEFAULTS = {
                    # Base API policies
                    'DEFAULT_RENDERER_CLASSES': (
                        'rest_framework.renderers.JSONRenderer',
                        'rest_framework.renderers.BrowsableAPIRenderer',
                    ),
                    'DEFAULT_PARSER_CLASSES': (
                        'rest_framework.parsers.JSONParser',
                        'rest_framework.parsers.FormParser',
                        'rest_framework.parsers.MultiPartParser'
                    ),
                    'DEFAULT_AUTHENTICATION_CLASSES': (
                        'rest_framework.authentication.SessionAuthentication',
                        'rest_framework.authentication.BasicAuthentication'
                    ),.....}
View Code
DEFAULT_AUTHENTICATION_CLASSES在self.defaults中,执行try
val = self.user_settings[attr],找到self.user_settings
 @property
                def user_settings(self):
                    if not hasattr(self, '_user_settings'):
                        self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
                    return self._user_settings
self.user_settings就是getattr的结果
getattr(settings, 'REST_FRAMEWORK', {})在settings文件中反射REST_FRAMEWORK
如果setting配置了self.user_settings的值就为配置的结果,如果未配置,就未{}

情况1:在settings中配置了REST_FRAMEWORK
REST_FRAMEWORK={
                    "DEFAULT_AUTHENTICATION_CLASSES":(
                          "app01.service.auth.AuthUser",
                     ),}
此时self.user_settings={"DEFAULT_AUTHENTICATION_CLASSES":("app01.service.auth.AuthUser",),}
情况2:未配置self.user_settings={}
          try:
                    val = self.user_settings[attr]
                except KeyError:
                    val = self.defaults[attr]
                在self.user_settings中找到DEFAULT_AUTHENTICATION_CLASSES的值
1.如果能找到val就为这个值,在配置的情况下,val等于我们自定义的值("app01.service.auth.AuthUser",)
2.未找到,就去self.defaults中找,并取值,此时值为默认设置的
val=(
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
)
 在当前类中未定义认证组件时,去APIView中调用对应的属性,在去settings中找REST_FRAMEWORK变量,如果这个变量存在,就取到
以这个属性为key的键值对的value作为authentication_classes的值
settings未自定义REST_FRAMEWORK变量,就使用默认设置,即DEFAULTS定义的value作为authentication_classes的值
在当前类中定义authentication_classes的话:将类进行实例化处理
1.self.get_authenticators()=[AuthUser()]
2.在当前类未定义,在settings中设置的话,就将settings对应的values进行实例化处理:self.get_authenticators()=[AuthUser()]
3.settings中未设置,实例化DEFAULTS中对应的values值:self.get_authenticators()=[SessionAuthentication(),BasicAuthentication()]

5.self.authenticators的值就为实例对象的集合

 for authenticator in self.authenticators:
                try:
                    user_auth_tuple = authenticator.authenticate(self)
                except exceptions.APIException:
                    self._not_authenticated()
                    raise
    
                if user_auth_tuple is not None:
                    self._authenticator = authenticator
                    self.user, self.auth = user_auth_tuple
                    return
View Code
首先执行try,执行实例对象中的authenticate方法,因此在自当以类中,我们在设置时,函数名必须是这个,返回值为user_auth_tuple
如果执行有误,就抛异常
如果user_auth_tuple的值不为空,就将值分别赋给user,auth,因此我们在设计时,要返回一个元祖,返回值可用request来调用

6.self.perform_authentication(request)

self._authenticate()的值就是authenticate函数执行的结果,从而request.user的值就是authenticate函数执行的结果
因此self.perform_authentication(request)执行的就是authenticate函数

整体流程

流程1:

流程2:

流程3


posted @ 2018-06-22 10:28  JERD  阅读(281)  评论(0编辑  收藏  举报