zoukankan      html  css  js  c++  java
  • 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


  • 相关阅读:
    #Leetcode# 448. Find All Numbers Disappeared in an Array
    #Leetcode# 65. Valid Number
    #Leetcode# 37. Sudoku Solver
    #Leetcode# 25. Reverse Nodes in k-Group
    POJ 3264 Balanced Lineup
    HDU 3947 Assign the task
    Codeforces Round #546 (Div. 2)
    2019.08.18【NOIP?提高组】模拟 A 组 总结
    jzoj 6307. 安排
    jzoj 6305. 最小值
  • 原文地址:https://www.cnblogs.com/zgf-666/p/9212214.html
Copyright © 2011-2022 走看看