rest-framework之身份验证和权限源码解读

身份验证

身份验证说白了就是用户在输入信息之后发送请求到服务端,服务端在校验成功之后将响应数据发送给客户端,然后用户在访问该网站的时候只需要携带着响应数据中的某些信息就可以访问了.

在这里,我们还拿示例项目进行解析.

要做身份验证,首先我们要设计url,如下

然后需要在app的views.py中写对应的视图类

get_random_str方法是模拟做的token中,生成的是一个随机的字符串

 当然这一部分做好之后就是如何应用的问题了,以及如何应用.请看下图,写在类里面的是局部验证,

上面的验证类如果继承的是BaseAuthentication类,那么就不用写authenticate_header方法了,实现的都是验证类,作用都是一样的

呈现的效果如果访问的是books没有携带token的值:

如果携带的有token的值是可以查询到的.

访问publishes没有携带token的值也可以访问到,原因上面已经说了,是因为book的视图类中写的有authentication_classes,它是作用于局部

那么如何设置全局的呢,对所有的视图类都其作用呢,其实只需在项目的settings中设置上下面设置就可以了,

 

这样它的作用范围就是所有继承了APIView的视图类,局部配置的优先级高于全局配置的,所以如果某个类不想要被验证,只需要在视图类中设置authentication_classes=[ ]就可以避免全局配置被验证了

如果不相信我上面的描述,那么我们以源码为证.

身份验证的源码解读

从我们的url开始,视图类BookView.as_view()是什么,我们先在BookView类中去找,里面没有as_view()方法,所以我们去它的父类ListCreateAPIView中去找

 在ListCreateAPIView里面也没有找到as_view(),这个类里面只有两个和请求相关的方法,所以我们继续往它的父类GenericAPIView中找.

 

我们可以看到GenericAPIView类中也没有as_view(),但它继承的是APIView类.,所以我们继续找APIView

我们可以看到APIView类继承了View类,但是APIView中有as_view()方法

as_view()的执行结果return给在url中调用它的BookView.as_view().所以此时url中应该是url(r'books/$',view),一旦匹配成功就会执行view,我们view是函数的函数名,所以我们又一层一层的进入到了APIView中的as_view()中,但是没有view的函数,所以它又会进入到它的父类View类中执行dispatch()方法,由于子类APIView类有dispatch()方法,所以就执行子类的dispatch方法.

 

 

我们需要到initialize_request()中看一看是对request进行了怎样的处理,如下图,该方法执行之后返回的是Request类的实例对象,我们需要看看Request这个类对原来的request进行了什么样的处理,里面的user又是什么,我们猜测一下,user应该是一个静态方法,下面我们再去源码中验证我们的猜想是否正确

 看上图,authenticators的值是调用了get_authenticators()之后得到的,再去看一下get_authenticators中做了什么,它返回的是一个列表,列表中的元素是自定义的认证类的实例对象.当然此时的authentication_classes必须在视图类中提供

authentication_classes=[认证类的类名1,],我们把get_authenticators中的返回值按照关键字传参,传给了Request实例时的形参authenticators,所以for循环authenticators得到的是认证类的实例对象,如果使用默认的authentication_classes,需要在settings中做配置,在settings中做设置是对全部的视图类都起作用的,在请求访问的时候都会进行认证,APIView类中为我们定义的有默认值,这里在后面在说,这里先讲解设置局部的,其实局部的和全局的也就是从这个地方根据使用的authentication_classes来区分的.

设置局部的

 

 我们把get_authenticators中的返回值按照关键字传参,传给了Request实例时的形参authenticators,所以for循环authenticators得到的是认证类的实例对象,认证类的实例对象又调用authenticate()方法,说明这个认证类中必须有这个方法,由下图中的代码执行情况可以确定的是authenticate()方法的返回值是一个元祖,也就是说user_auth_tuple是一个元祖.在if判断为True,取出元祖中的两个元素,一个是user,一个是auth,当然在写authenticate()方法时,返回值可以根据自己的实际情况来返回,但是返回的东西要能够取到用户名.

到此为止,局部的设置视图类的认证就已经解读完了,作用范围是只对写有authentication_classes=[认证类的类名]的视图类起作用,就如本篇文章一开始讲解的一个实例小项目中的代码截图以及最终的运行结果的截图那样.那么如果我要是想设置全局的,源码中又是如何实现的呢,.我们继续解读源码.

设置全局的认证

在执行get_authenticators()方法时,我已经说过了,如果它在视图类中找不到authentication_classes,就会使用它自己的,它自己的authentication_classes是在APIView中定义的静态属性,如下图,api.settings又是什么,它调用后面的DEFAULT...的方法才能获得authentication_classes,我们点进去看看api_settings

api_settings其实就是一个实例对象,如下图,它是APISettings类的实例对象,那么就能说明那个DEFAULT....的方法就在这个类中.先不着急进这个类里面去看,根据下图,我们可以看到这个类实例化的时候第一个参数是None,第二个值才是DEFAULTS,那么也就是说我传进去的第一个参数我可以自己定义,如果我没传,它就传入None

下面图中的是APISettings类中的一些代码,在初始化方法中,它判断了user_settings是否为None,我们先假设它不为None时,后面的代码经过一系列的查找就是查找项目的settings中是否有REST_FRAMEWORK这个东西.

 根据下面源码中的这段代码可以看出,它是要找我是否在settings中配置了REST_FRAMEWORK,(必须写这个名字,如果换个就会找不到,然后就会使用它的APISettings类的第二个参数了,第二个参数后面再说,),下面截图中说如果找不到这个配置的名字就会返回一个空字典,那么就说明我需要在项目的settings中定义一个名字为REST_FRAMEWORK={},它的键就是api_settings调取的方法的方法名,值为认证的类所在文件的文件的路径

例如在settings中设置成这样

只要在settings中设置上就对全局的视图类生效了.如果不想要某个视图也进行认证,那就在该视图类中设置authentication_classes=[],设置它为一个空列表,就可以不用认证了,因为在类中找的时候是现在视图类中找,找不到才会使用APIView给的静态属性,然后才会去找settings中有没有全局的认证的配置.所以局部的生效了就不会找全局的了

如果APISettings类中第一个参数为None,也就是说我没有在settings中设置,那么再看第二个参数DEFAULTS,点DEFAULTS进去看一下,里面是restful-framework给出的默认值.,到这里就没有必要再继续往下看了.关于认证的源码就解读到这里结束.

 权限的源码解读

其实权限的源码和认证的逻辑都是一样的,不信你看源码

是不是一样的,好了,我就不说了,和上面的流程都是一样的,

频率

下面这个是频率的,也是和认证的流程一样的,这里我就不多赘述了

 

 

posted @ 2018-04-10 23:56  dwenwen  阅读(53)  评论(0)    收藏  举报