美文网首页
Django Rest Framework 源码解析--认证

Django Rest Framework 源码解析--认证

作者: 叶_叶 | 来源:发表于2019-12-23 11:05 被阅读0次

    Django Rest Framework 源码解析--认证

    上一篇文章;restframework重写的dispatch()方法中,执行了inital()函数。其中perform_authentication(request) 方法实现了请求的认证功能。
    1、perform_authentication()函数中执行了Request类(rest_framework.reqeust.py中定义的类)的对象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方法(是个property所以不用user() )
        request.user
    

    2、经过一些判断之后,跳转到** _authenticate()** 方法

    class Request(object):
        """
        Wrapper allowing to enhance a standard `HttpRequest` instance.
        Kwargs:
            - request(HttpRequest). The original request instance.
            - parsers_classes(list/tuple). The parsers to use for parsing the
              request content.
            - authentication_classes(list/tuple). The authentications used to try
              authenticating the request's 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
    

    3、在Request类的_authenticate()方法中,执行** authenticators**(认证对象列表) 中的每一个认证对象的 **authenticate() **方法。

    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:
                # 如果认证对象没有写authenticate()方法,抛出异常_not_authenticated()
                self._not_authenticated()
                raise
                
            # 如果写了authenticate()方法,并且执行后返回的不是None
            # 则给request对象实例生成3个成员 self._authenticator, self.user, self.auth
            if user_auth_tuple is not None:
                self._authenticator = authenticator
                self.user, self.auth = user_auth_tuple
                return
            # 如果执行authenticate()方法之后返回的是None
            # 则继续循环,执行对象列表中下一个 认证对象的方法,直到最后一个对象
        self._not_authenticated()
    # authenticate()的返回值应该是(should be)一个元祖,元祖的值 (self.force_user,  self.force_token)
    # 返回的值是最终通过认证的用户和token,这些会作为成员变量赋值给request,可以在view中调用self.user, self.auth
    def authenticate(self, request):
        return (self.force_user, self.force_token)
    

    使用示例:

    1、自定义一个认证类,继承BaseAuthentication

    class MyAuthentication(BaseAuthentication):
        '''用于用户登录验证'''
        def authenticate(self,request):
            token = request._request.GET.get('token')
            # UserToken自定义的存储token的表与用户表一对一关系
            token_obj = models.UserToken.objects.filter(token=token).first()
            if not token_obj:
                raise exceptions.AuthenticationFailed('用户认证失败')
            #在rest framework内部会将这两个字段赋值给request,以供后续操作使用
            return (token_obj.user,token_obj)
    

    2、想要调用认证类有两种方法

    ①在全局的setting.py文件中设置认证类的路径

    REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES": (
        'restframework_class.auth.MyAuthentication',
        )
    }
    

    ②在View中重写authentication_classes列表,调用认证类

    class TestView(APIView):
        # 重点看这一行,重写authentication_classes列表,调用认证类
        # 自定义的类MyAuthentication此时是最后一个认证类,所以必须返回(user, token)
        authentication_classes = (MyAuthentication, )
     
        def get(self,request,*args,**kwargs):
            pass
    

    相关文章

      网友评论

          本文标题:Django Rest Framework 源码解析--认证

          本文链接:https://www.haomeiwen.com/subject/takznctx.html