Django Rest Framework 认证功能-源码分析及使用技巧

LinuxNetworkCC 2019-06-30

pip3 install djangorestframework

认证源码梳理

  • 从rest_framework的dispatch开始入手观察源码

在dispatch中,对原生request进行了封装

def dispatch(self, request, *args, **kwargs):
    self.args = args
    self.kwargs = kwargs
    # 对原生的request进行加工,包含【原生request】丰富了authenticator
    request = self.initialize_request(request, *args, **kwargs)
    # 获取原生的request对象 request._request
    # 获取认证类对象 request.authenticators
    self.request = request
    self.headers = self.default_response_headers  # deprecate?
    
    try:
        # 2. 认证
        self.initial(request, *args, **kwargs)
    .....
  • 认证

跟进self.initial

def initial(self, request, *args, **kwargs):
    self.format_kwarg = self.get_format_suffix(**kwargs)

    '''版本处理'''
    neg = self.perform_content_negotiation(request)
    request.accepted_renderer, request.accepted_media_type = neg
    ......

    '''进行认证'''
    self.perform_authentication(request)
    '''权限控制'''
    self.check_permissions(request)
    '''访问频率'''
    self.check_throttles(request)
然后继续跟进,调用了.user._authenticate()方法 # 获取认证对象进行一个一个认证,如果错误就触发异常!

认证方法

这是认证和视图写在了一起,方便观看,实际中最好将认证类单独存放在一个py中
from rest_framework.views import APIView
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication  # 内置的认证类【必须继承】

class Authentication(BaseAuthentication): # 自己写认证,然后引用
    def authenticate(self, request):
        token = request._request.GET.get('token')
        token_obj = models.UserToken.objects.filter(token=token).first()
        if not token_obj:
            # 其实在内部捕捉了异常
            raise exceptions.AuthenticationFailed('用户认证失败')

        # 返回user对象 + token
        # 在rest framework 内部会将两个字段赋值给 request,给后面调用
        '''返回值必须是元祖 第一个赋值给 request.user  第二个request.auth'''
        return (token_obj.user, token_obj) 

    def authenticate_header(self, request):
        pass
        ...

class DogView(APIView):
    """
    应用上Authentication认证规则。如果有多个,那么依次认证
    如果都没有认证,那么默认值 request.user=AnonymousUser  request.auth = None  匿名用户
    request.user  这是token_obj.user 源码中规定元祖第一个
    request.auth  这是token_obj  源码中规定元祖第二个
    """
    authentication_classes = [Authentication, ]
    ......

源码流程图

Django Rest Framework 认证功能-源码分析及使用技巧

setting中配置认证类

实际中将自己写的认证方法单独放在一个py中,然后在项目setting中配置即可
# 导入自己写的rest 认证路径
"""
可以局部使用或者全局使用    
局部: authentication_classes = [] 
"""
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ['app01.utils.auth.Authentication', ],  # 全局使用的认证类,也可以局部使用
    "UNAUTHENTICATED_USER": None,  # 匿名用户, request.user = None
    "UNAUTHENTICATED_TOKEN": None,  # 匿名用户, request.auth = None
}

这样写的好处是无需再视图中再写引用了,会自动按照你setting中的配置进行认证,如果指定视图不需要认证,那么在该view中写 authentication_classes = [] 即可

内置的认证

  • BaseAuthentication 主要使用的就是这个
  • BasicAuthentication 浏览器内置的认证【大家了解下就是了】
  • 剩下的就是基于django的用户认证了

使用总结

  1. 创建类: 继承BaseAuthentication - 实现 authenticate方法
  2. 返回值结果
    None执行下一个认证
    raise认证失败抛出异常
    元祖(元素1,元素2)元素1=request.user; 元素2=request.auth
  3. 全局使用

    setting中配置,然后在单独的py文件中写入认证「写入路径」
  4. 局部使用

    在视图中 引入authentication_classes = [认证类, ]

相关推荐