djangorestframework的源码认证流程

1.APIView的大致执行流程

由于请求首先经过dispatch,所以我们写的CBV 首先要去找dispatch,自己写的没有要去父类APIView找
例:
class
OrderView(APIView): #authentication_classes = [MyAuthentications, ] def get(self, request, *args, **kwargs): self.dispatch print(request) ret = { 'code': 1000, 'msg': 'sdfa' } return HttpResponse(json.dumps(ret), status=201) def post(self, request, *args, **kwargs): return HttpResponse('创建订单')
在APIView中找到dispatch

 

 

上面代码中self.dispatch快速找到dispatch方法

#上述中的大致步骤为
1.对request进行加工
2.(1)处理版权信息
  (2)认证
  (3)权限  
  (4)频率限制
3.执行 get/post/put/delete函数,此request为加工后的request
4.对返回结果再次进行加工

2.接下来是Djangorestframework 的认证流程

1.封装request
#对原生的request进行加工
        #return Request( request,
               #封装了原生request,
               parsers=self.get_parsers(),
               authenticators=self.get_authenticators(),
               negotiator=self.get_content_negotiator(),
               parser_context=parser_context)
#现在我们对request进行了两个操作(原生request,[BasicAuthentication(),]) request = self.initialize_request(request, *args, **kwargs) #获取原生requests,request._requests #获取认证类的对象,request.authenticators self.request = request self.headers = self.default_response_headers # deprecate? #进入initalize_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(), #[BasicAuthentication(),] #实例化对象 authenticators=self.get_authenticators(), negotiator=self.get_content_negotiator(), parser_context=parser_context ) #这里封装了原生request、认证、版本控制、上下文解析等方法 def get_authenticators(self): """ Instantiates and returns the list of authenticators that this view can use. """ return [auth() for auth in self.authentication_classes] #实例化
  •   若想要调用APIView中的方法,ctrl+Request 到request.py中
    •    self._request = request
          self.parsers = parsers or ()
          self.authenticators = authenticators or ()
          self.negotiator = negotiator or self._default_negotiator()
          self.parser_context = parser_context
          self._data = Empty
          self._files = Empty
          self._full_data = Empty
          self._content_type = Empty
          self._stream = Empty
          例:request._request.POST.get('username')
#2.认证
    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
        #4.实现认证
        # 含原生的以及认证
        self.perform_authentication(request)

        #做频率限制的
        self.check_permissions(request)
        self.check_throttles(request)
#ctrl 进入我们实现认证的方法  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是APIView的,执行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



#执行self._authenticate() 开始用户认证,如果验证成功后返回元组: (用户,用户Token) def _authenticate(self): """ Attempt to authenticate the request using each authentication instance in turn. """ #[BasicAuthentication对象] #循环对象列表 for authenticator in self.authenticators: try: #执行对象的authentication方法 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 return
#如果认证成功,执行_authenticate方法,若认证失败抛出异常调用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()
        else:
            self.user = None

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

例子:自定义认证类

class MyAuthentications(object):
    def authenticate(self, request):
        token = request._request.GET.get('token')
        print(token)
        if not token:
            raise exceptions.AuthenticationFailed('用户认证失败')
        return ('xinzong', None)

    def authenticate_header(self, val):
        pass


class OrderView(APIView):
    authentication_classes = [MyAuthentications, ]

    def get(self, request, *args, **kwargs):
        self.dispatch
        print(request)
        ret = {
            'code': 1000,
            'msg': 'sdfa'
        }
        return HttpResponse(json.dumps(ret), status=201)

    def post(self, request, *args, **kwargs):
        return HttpResponse('创建订单')

效果图:

未带token

 

携带token

 
 
posted @ 2020-08-24 15:31  手可摘星辰/*  阅读(172)  评论(0编辑  收藏  举报