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

pip3 install djangorestframework

认证源码梳理

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

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

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.initialdjango

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, ]
    ......

源码流程图

image

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. 全局使用app

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

    在视图中 引入authentication_classes = [认证类, ]
相关文章
相关标签/搜索