Django Rest Framework 身份认证源码详解

一.Django确实是一个很强大,用起来很爽的一个框架,在Rest Framework中已经将身份认证全都封装好了,用的时候直接导入authentication.py这个模块就好了。这个模块中5个认证类。但是我们在开发中很少用自带的认证类,而是根据项目实际需要去自己实现认证类。下面是内置的认证类

 

  • BaseAuthentication(object):所有的认证相关的类都继承自这个类,我们写的认证类也要继承自这个认证类,类中面有两个方法,authenticate(self,request):这个方法是我们开发中用的最多的,还有一个方法:authentication_header(self,request):这个方法主要是给浏览器返回响应头的。
     
  • BasicAuthentication(BaseAuthentication):这个是基于浏览器实现的认证类。
     
  • SessionAuthentication(BaseAuthentication):使用Django的会话框架进行身份验证。
     
  • TokenAuthentication(BaseAuthentication):简单的基于令牌的身份验证。客户端应通过在“授权”中传递令牌密钥进行身份验证
    HTTP头,前面加上字符串“Token”

     
  • RemoteUserAuthentication(BaseAuthentication):远程用户身份验证。
     
    在这里插入图片描述

二.身份认证的两种实现方式:

 
 
1.第一种方式就是在views.py模块中去创建一个认证类,这个认证类必须重写authenticate()这个方法,这个方法必须返回一个元组,里面返回用户和token值,然后在需要认证的类视图中注册上这个认证类:authentication_classes = [AuthClass,],authentication_classes名字也不能改,后面讲源码的时候会告诉大家为什么这么写。这是第一种认证方式。
在这里插入图片描述
 

2.
①:第二中方式是在settings中配置认证模块,这种方式是全局身份认证。首先创建一个utils工具包,然后创建一个auth.py身份认证模块。把认证类写在这里面。这是开发中经常使用的方式,这样views.py中全是类视图,把认证类放到认证模块中,符合高内聚,低耦合的编程思想,也方便后期管理维护。

 
在这里插入图片描述
 

②:然后将这个认证模块注册到settings.py中,这是全局认证,所有的类视图都会进行身份认证。
 
在这里插入图片描述
 

③:用户登录的借口是不需要身份认证的,所以在用户登录接口中加上authentication_classes = [],这样登录接口就不会进行身份认证了。
在这里插入图片描述
 

三.下面来看一下身份认证源码解析流程。

 
1.首先当一个请求过来的时候,先走路由的as_view()方法,as_view()方法中调用了dispatch方法,rest framework 中的APIView(view)继承自django中的view,然后重写了dispatch()方法,于是走APIView中的dispatch()方法。
 
在这里插入图片描述
 

2.重写的dispatch()对django的request进行了重新的封装,调用了initizlize_request()方法对request进行封装,我们进入initizlize_request()这个方法再看一下做了什么操作。
 

在这里插入图片描述
 

3.initializer_request()这个方法中调用了get_authenticators()得到认证对象的这个方法,我们再进入这个方法看一下做了什么。
 
在这里插入图片描述
 

4.进入get_authenticators()中发现,这个方法中有一个列表生成器,用来实例化当前认证类,这就是为什么之前要在类视图中注册认证类必须要用这个名字的原因,因为源码中规定了认证类读取的名字。所以,如果我们自己写了认证类,他会在类视图中找到我们的认证类并执行返回,如果我们没有写认证类呢?会怎么执行?我们继续往下看,看看列表生成器中调中的authentication_classes这个属性它是从哪获得的。
 
在这里插入图片描述
 

5.我们发现authentication_classes默认是从settings中配置获得的。所以这也是为啥可以把认证类配置在settings中的原因。然后这就是initizlize_request()方法对request的认证封装的执行流程,封装完后在dispatch()中继续往下执行,当前只是实例化认证类,并没有执行认证。然后我们接着看dispatch()下面认证的执行流程
 
在这里插入图片描述
 

6.dispatch()调用initial(request, *args, **kwargs)这个方法进行认证,我们看下initial(request, *args, **kwargs)这个方法做了什么。

 
在这里插入图片描述
 

7.initial(request, *args, **kwargs)这个方法中又调用了三个方法:
  • perform_authentication(request):身份认证方法
  • check_permissions(request):权限验证方法
  • check_throttles(request):节流方法
    我们看下perform_authentication(request):身份认证方法都干了些什么。
     

在这里插入图片描述
 
8.perform_authentication(request):身份认证方法只调用了一个user方法,我们继续看user这个方法。
 
在这里插入图片描述
 
9.user这个方法调用了_authenticate()这个方法,继续往下看。
 
在这里插入图片描述
 
10.这次只终于到底了,_authenticate()方法中遍历认证类的所有对象,执行认证类的authenticate方法,这个就是我们写的身份认证方法,这个方法要返回一个元组,我们看下authenticate方法。
 
在这里插入图片描述
 
11.authenticate()方法返回一个元组,元组中包含当前对象和token值,所以我们重写authenticate()方法也要返回这个元组。这样整个认证执行流程就全结束了。如果authenitcate()方法抛出异常,就被捕获并执行 self._not_authenticated(),认证不通过并直接返回,就不会走dispatch()下面反射机制找视图函数方法了,反射机制上篇博客我详细的说过了,这里就不说了,如果没有抛出异常,继续走dispatch()下面的代码。
 
在这里插入图片描述
  
 
在这里插入图片描述


版权声明:本文为weixin_43697214原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。