DRF源码学习-Authentication
原创2022年1月31日
认证组件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...