DRF源码学习-Authentication

MicLon原创2022年1月31日
大约 2 分钟

认证组件Authentication

All authentication classes should extend BaseAuthentication. 所有认证类都应该继承于BaseAuthentication —— 来自BaseAuthentication类注释

1.BaseAuthentication

BaseAuthentication为认证类的基类,其中有两个方法:

  • authenticate
    • 这个方法必须被子类实现,用于检测认证是否通过,且必须返回元祖(user, token),值得注意的一点,当方法返回None的时候会跳过此验证,继续下一个验证,如果想认证不通过,则需要抛出AuthenticationFailed异常。
  • authenticate_header
    • 这个方法子类也可以不去覆盖,默认情况下,当授权未通过,展示返回headers中key为WWW-Authenticate的value

2.编写自己的认证组件

在这里我直接最简易的判断header来检测认证

class MyAuthentication(BaseAuthentication):
    # 实现父类中的authenticate方法
    def authenticate(self, request):
        if request.META.get("HTTP_AUTHORIZATION") == 'miclon':
            return (None, None)
        raise AuthenticationFailed('认证不通过')
        
    def authenticate_header(self, request):
        return "get out"

当启用header的时候: 当关闭此header的时候: 同时可以在返回header中观察到:

3.认证组件原理

在APIView类中,认证组件读取Django设置项中DEFAULT_AUTHENTICATION_CLASSES的列表作为默认认证类

class APIView(View):
	……
	authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    ……

所以,当继承APIView的子类,使用覆盖authentication_classes的方式,即可自定义该子类的认证类

class TestView(APIView):
    authentication_classes = [MyAuthentication]

    def get(self, request):
        return JsonResponse({"result": "success"})

又由于APIView是继承自Django的View,Django的View是由dispatch方法来调度的,APIView重写了此方法,在初始化获取request实例的时候,将子类中所有的认证类传递给Request类

来看看Request类干了什么事。 不难看出,它for循环遍历了所有认证组件,分别去执行其中的authenticate方法,当出现APIException异常的时候抛出错误。 再回过头看看,当我们认证不允许通过的时候,抛出AuthenticationFailed的异常,而它实际上是继承自APIException,且覆盖了出错的状态码为401

以上就是针对DjangoRestFramework中认证组件的简要解读。

Loading...