一、认证源码流程

1、认证准备工作

rest framework之APIView中提到过rest framework的视图不仅有CBV分发的特性,而且又对request进行了封装,其中封装的就有认证功能。在APIView类下的dispatch方法中:

 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
        #rest-framework重构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
            #这里和CBV一样进行方法的分发
            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

            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

在dispatch方法中:

  request = self.initialize_request(request, *args, **kwargs)

是重构request对象,initialize_request返回的就是一个request对象,封装了原request以及认证相关:

    def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)

        return Request(
            request, #传入原request
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(), #认证相关
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

在request对象中封装了authenticators这一个个写好的认证类的对象,可以自己配置的认证类,这样认证的准备工作已经完成了(其实就是request封装认证类对象的列表)。

2、认证过程

在dispatch方法中的代码中:

 self.initial(request, *args, **kwargs) #request是已经重构的request

在initial方法中:

    def initial(self, request, *args, **kwargs):
    
        ...

        # Ensure that the incoming request is permitted
        self.perform_authentication(request) #进行认证

        self.check_permissions(request)
        self.check_throttles(request)    

在perform_authentication方法中:

    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封装对象

#方便寻找,导入
from rest_framework.request import Request
    @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

在_authenticate方法中

    def _authenticate(self):
        """
        Attempt to authenticate the request using each authentication instance
        in turn.
        """
        """
        三种情况:
        1、正常的认证,元组不为空
        2、认证失败,没有通过认证类中认证方法的检验,没有登陆
        3、匿名用户,认证类中认证方法没有检验,返回的是None
        """
        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._not_authenticated() #匿名用户执行
 def _not_authenticated(self):
        """
        Set authenticator, user & authtoken representing an unauthenticated request.

        Defaults are None, AnonymousUser & None.
        """
        self._authenticator = None

        if api_settings.UNAUTHENTICATED_USER:
            self.user = api_settings.UNAUTHENTICATED_USER() #在settings中可以设置默认的
        else:
            self.user = None #如果settings中没设置默认的就执行

        if api_settings.UNAUTHENTICATED_TOKEN:
            self.auth = api_settings.UNAUTHENTICATED_TOKEN()
        else:
            self.auth = None
_not_authenticated

相关文章: