Django Rest Framework 源码解析--认证

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

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值