美文网首页
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