django rest framework系列04-状态认证晋级代码详细流程

 以这个url为例:

path('api/v1/order/',views.orderView.as_view()),

我们只有一个get方式,那么请求进来先去执行 self.dispatch,我们没有写(覆盖),就去父类(继承与APIView)执行

class orderView(APIView):
    """
    用于处理订单相关业务
    """
    authentication_classes = [Authtication,] #DEFAULT_PERMISSION_CLASSES默认去配置文件找,这里自定义一个
    def get(self,request,*args,**kwargs):
        ret = {'code':1000,'msg':None,'data':None}
        try:
            ret['data'] = ORDER_DISK
        except Exception as e:
            pass

        return JsonResponse(ret)

 也就是说第一步执行APIView中有中的dispatch。dispatch内部流程:

  1. 对request进行封装。

    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 = self.initialize_request(request, *args, **kwargs)  #封装request
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

 1.1封装(封装了authenticators)部分代码:

  • 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(),
            authenticators=self.get_authenticators(), #这里封装了一个authenticators,调用get_get_authenticators()。我们views中没有定义,那么继续在父类中找。
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
  • 1.2: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我们views也没有定义,所以还是去父类中找,

 1.3.self.authentication_classes定义 authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES,指向配置文件:api_settings的DEFAULT_AUTHENTICATION_CLASSES。

也就是说DEFAULT_AUTHENTICATION_CLASSES默认是在配置文件中,如果我们在views中设置了,那么就会覆盖掉。直接用我们自定义的。

class Authtication(object):

    def authenticate(self,request):
        #user_auth_tuple = authenticator.authenticate(self)跟踪得到,默认调用authenticate方法,返回一个元组
        token = request._request.GET.get('token')
        token_obj = models.UserToken.object.filter(token=token).first()

        if not token_obj:
            raise exceptions.APIException('用户认证失败')

        return (token_obj.user,token_obj.token)

    def authenticate_header(self,request):
        '这个方法暂时不知道干啥,不加保存,加上不用先'
        pass

2、调用initial(进行认证)

2.1、进入initial内部看看执行了什么

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)  #第一个执行了perform_authentication传入了刚才包装好的request
    self.check_permissions(request)
    self.check_throttles(request)

2.2 self.perform_authentication(request)内部调用了 request.user:

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:内部又调用了self._authenticate()

@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()。循环self.authenticators,这个不就是上一步封装的那个认证类列表,也就是我们views中定义(覆盖)的那个列表。再看内部的方法每个类必须有一个authenticate方法。返回要给元组,

def _authenticate(self):
    """
    Attempt to authenticate the request using each authentication instance
    in turn.
    """
    for authenticator in self.authenticators:
        try:
            #执行封装好的认证类的authenticate方法,
            #如果这个方法抛出异常,这里except exceptions.APIException就可以抛出异常raise又再向上抛出异常
            #1如果又返回值,则执行下面if user_auth_tuple is not None:,把元组的值赋值给,user,auth,如果认证成功下面直接return,结束循环,
            #如果没有返回值,跳过循环,进入下一次循环认证。
            #如果都没有返回值,那么执行,self._not_authenticated()
            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()

返回的元组:那么我们就可以自定义个这个类,也返回一个元组。(user,token)

def authenticate(self, request):
    return (self.force_user, self.force_token)

 

 如果没有返回值,执行到了self._not_authenticated(),源代码这样:

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

    Defaults are None, AnonymousUser & None.
    """
    self._authenticator = None
    #如果UNAUTHENTICATED_USER存在那么久把self。user的值调用配置文件UNAUTHENTICATED_USER,这里去到配置文件可以看到是一个django.contrib.auth.models.AnonymousUser
    #也就是说默认赋值,匿名用户
    if api_settings.UNAUTHENTICATED_USER:
        self.user = api_settings.UNAUTHENTICATED_USER()
    else:
        self.user = None
    #token也是跟上面一个取配置文件,'UNAUTHENTICATED_TOKEN': None,
    if api_settings.UNAUTHENTICATED_TOKEN:
        self.auth = api_settings.UNAUTHENTICATED_TOKEN()
    else:
        self.auth = None

3、执行反射(判断请求方式进行匹配view)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值