DRF认证之源码详解

一. DRF认证之源码详解

  1. dispatch()源码执行流程详解

    客户端所有的请求到来之后都会执行dispatch()方法,dispatch()方法会根据不同的请求方式,从而触发不同的方法,如GET/POST/PUT/DELETE/UPDATE等方法.

    • 第一步对request进行封装(添加数据)
      request = self.initialize_request(request, *args, **kwargs)

    • 第二步:initial(request, *args, **kwargs):
      #处理版权信息
      #认证
      #权限
      #请求用户进行访问频率的限制

    • 第三步,执行:get/put/post/delete函数

      ​ handler(request, *args, **kwargs)

    • 第四步,对返回结果再次进行加工
      self.response = self.finalize_response(request, response, *args, **kwargs)

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        #第一步对request进行封装(添加数据)
        request = self.initialize_request(request, *args, **kwargs)   
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
    
        try:
            #第二步:
                #处理版权信息
                #认证
                #权限
                #请求用户进行访问频率的限制    
            self.initial(request, *args, **kwargs)
            
            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
                
            #第三步,执行:get/put/post/delete函数
            response = handler(request, *args, **kwargs)
        
        except Exception as exc:
            response = self.handle_exception(exc)
            
        #第四步,对返回结果再次进行加工
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
    

接下来对每一步进行详解:

  • 第一步对request进行封装(添加数据)

    def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        #请求封装成一个字典返回
        parser_context = self.get_parser_context(request)
    
        return Request(
            request,
            parsers=self.get_parsers(),  # 解析数据,默认有三种方式,可点进去看
            #self.get_authenticators() 先找自己的,没有就找父类的
            authenticators=self.get_authenticators(),#获取认证相关的所有数据并实例化,传入request对象并供request使用
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
    
  • 获取认证相关的类具体 authenticators=self.get_authenticators()

    def get_authenticators(self):
            """
            Instantiates and returns the list of authenticators that this view can use.
            """
            #返回一个对象列表
            return [auth() for auth in self.authentication_classes]
    
  • 查看认证相关的self.authentication_classes

    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES 	#默认的
    
  • 接着点击api_settings

    api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)  #接着点击继承的DEFAULTS
    
    #这时候就找到了
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication'
    
  • 导入SessionAuthentication、BasicAuthentication类:

    from rest_framework.authentication import SessionAuthentication
    from rest_framework.authentication import BasicAuthentication
    
  • 看看authenticate,authenticate_header两个方法

    class BaseAuthentication:
        """
        All authentication classes should extend BaseAuthentication.
        """
    
        def authenticate(self, request):
            """
            Authenticate the request and return a two-tuple of (user, token).
            """
            raise NotImplementedError(".authenticate() must be overridden.")
    
        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
        	pass
    

第二步:查看self.initial(request, *args, * *kwargs):

    def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg
        #处理版本信息
        # Determine the API version, if versioning is in use.
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        #认证
        self.perform_authentication(request)
        #权限
        self.check_permissions(request)
        #限流
        self.check_throttles(request)
  • 点击看一下认证的self.perform_authentication(request)
    def perform_authentication(self, request):
        """
        Perform authentication on the incoming request.

        Note that if you override this and simply 'pass', then authentication
        will instead be performed lazily, the first time either
        `request.user` or `request.auth` is accessed.
        """
        request.user #执行request的user,这里的request已经是加工后的request了
  • 看一下request.user这个属性
@property
    def user(self):
        """
        Returns the user associated with the current request, as authenticated
        by the authentication classes provided to the request.
        """
        if not hasattr(self, '_user'):
            with wrap_attributeerrors():
                self._authenticate() #用户开始认证了
        return self._user   #返回user

  • 执行self._authenticate() 开始用户认证,如果验证成功后返回元组: (用户,用户Token)
    def _authenticate(self):
        """
        Attempt to authenticate the request using each authentication instance
        in turn.
        """
        #循环对象列表
        for authenticator in self.authenticators:
            try:
                #执行每一个对象的authenticate方法
                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  #返回一个元组,user,和auth,赋给了self,
                # 只要实例化Request,就会有一个request对象,就可以request.user,request.auth了
                return

        self._not_authenticated()
  • 在user_auth_tuple = authenticator.authenticate(self) 进行验证,如果验证成功,执行类里的authenticatie方法

    如果用户没有认证成功:self._not_authenticated()

def _not_authenticated(self):
        """
        Set authenticator, user & authtoken representing an unauthenticated request.

        Defaults are None, AnonymousUser & None.
        """
        #如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
        self._authenticator = None  #

        if api_settings.UNAUTHENTICATED_USER:
            self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户AnonymousUser
        else:
            self.user = None  # None 表示跳过该认证

        if api_settings.UNAUTHENTICATED_TOKEN:
            self.auth = api_settings.UNAUTHENTICATED_TOKEN()  # 默认值为:None
        else:
            self.auth = None

    # (user, token)
    # 表示验证通过并设置用户名和Token;

第三步:执行GET/POST/PUT/DELETE等方法

第四步:对第三步返回结果进行加工

原文地址:https://www.cnblogs.com/maqian/p/12957090.html