1 绪言

上一篇中分析了认证部分的源码,认证后的下一个环节就是权限判定了。事实上,权限判定肯定要与认证联合使用才行,因为认证部分不会对请求进行禁止或者是允许,而只是根据请求中用户信息进行用户身份判断,而权限判定就是认证中添加的用户身份进行权限判定。权限判定的入口在dispatch方法中调用的initial方法中,如下所示:

def initial(self, request, *args, **kwargs):
……
# Ensure that the incoming request is permitted
self.perform_authentication(request) #认证
self.check_permissions(request) #权限判定
self.check_throttles(request)

2 源码分析

当执行check_permissions方法的时候,权限判定也就开始了,贴出check_permissions方法的源码:

def check_permissions(self, request):

    for permission in self.get_permissions():#遍历所有权限类实例

        if not permission.has_permission(request, self):#如果没有权限则执行下列代码

            self.permission_denied(

                request, message=getattr(permission, 'message', None)

            )

        #有权限的话继续下一个权限类实例,直到遍历完所有实例
  
    check_permissions方法首先遍历权限类实例列表,这个列表从哪来呢?我们看看get_permissions方法就知道了:
def get_permissions(self):
return [permission() for permission in self.permission_classes]
    这两行代码有没有很眼熟?没错,在上一篇认证源码分析中也有一个列表生成式生成所有配置好的权限类实例,连读取权限类的方式都是一样的,与权限类不同的是,认证类的这个环境放在加工处理request请求的方法中,然后将所有认证类实例封装进了request中。当然,这跟权限类没关系,我们现在只需要知道这个方法会读取配置的权限类,然后依次实例化并返回列表。但值得注意的是,里面有一个message属性,是指拒绝访问之后返回的提示信息,自定义权限类的时候可以指定message的值。
在for循环中,不断遍历权限实例对象,执行它的has_permission方法,我们以djangorestfromework自带的AllowAny为例进行分析
class AllowAny(BasePermission):

    def has_permission(self, request, view):

        return True

AllowAny类的has_permission方法直接就返回一个True,因为AllowAny这个类的功能就是允许所有访问,也就是说在has_permission类中,如果允许访问,就返回True,拒绝访问就返回False。

权限实例对象列表中可能有多个权限类实例,只要有一个返回的是False,抛出异常,那么就拒绝访问。这个异常是就是在permission_denied方法中抛出的,这个方法会在has_permission方法返回False时执行,permission_denied的作用就是判断抛出那种异常,源码如下:

def permission_denied(self, request, message=None):

    if request.authenticators and not request.successful_authenticator:

        raise exceptions.NotAuthenticated()

    raise exceptions.PermissionDenied(detail=message)
如有所有权限类都遍历完了,都返回True,那么权限判定这个环节就结束了。

3 自定义权限类

     自定义的权限类必须实现has_permission方法,另外可以在类中指定拒绝访问时的message,当然这不是必须的。以下是自定义的一个权限类,功能是只允许用户名为“admin”的用户访问,
拒绝其他所有用户,拒绝是提示“您不是admin用户,无权访问”:
from rest_framework.permissions import BasePermission

class MyAdminPermission(BasePermission):

    message = '您不是admin用户,无权访问'

    def has_permission(self, request, view):

        if request.user == "admin":

            return True

4 配置权限类

    配置权限类的方法和配置认证类差不多:
    局部配置:
    在视图类中加入以下代码:
DEFAULT_PERMISSION_CLASSES = [MyAdminPermission,]
注意:别忘了逗号。
全局配置:
在项目的settings.py文件中加入:
REST_FRAMEWORK = {

    'DEFAULT_PERMISSION_CLASSES': [

        'myapp.util.permission. MyAdminPermission ',

    ]
}

三、django rest_framework源码之权限流程剖析的更多相关文章

  1. 二、django rest_framework源码之认证流程剖析

    1 绪言 上一篇中讲了django rest_framework总体流程,整个流程中最关键的一步就是执行dispatch方法.在dispatch方法中,在调用了一个initial方法,所有的认证.权限 ...

  2. 一、django rest_framework源码之总体流程剖析

    1 序言 有如下django代码,视图层: from django.http import HttpResponse from rest_framework.views import APIView ...

  3. 六、django rest_framework源码之解析器剖析

    1 绪论 网络传输数据只能传输字符串格式的,如果是列表.字典等数据类型,需要转换之后才能使用但是我们之前的rest_framework例子都没有转换就直接可以使用了,这是因为rest_framewor ...

  4. 四、django rest_framework源码之频率控制剖析

    1 绪言 权限判定之后的下一个环节是访问频率控制,本篇我们分析访问频率控制部分源码. 2 源码分析 访问频率控制在dispatch方法中的initial方法调用check_throttles方法开始. ...

  5. 七、django rest_framework源码之视图

    1 绪言 当大家看大这篇博文的时候,应该对Django rest_framework中的CBV有所了解了,大致来说就是通过定义类来继承APIView类,并在类中定义get.post.put.delet ...

  6. 五、django rest_framework源码之版本控制剖析

    1 绪论 Djangorest_framework的版本控制允许用户更改不同客户端之间的行为,且提供了许多不同的版本控制方案.版本控制由传入的客户端请求确定,可以基于请求URL,也可以基于请求标头. ...

  7. Django session 源码流程

    流程 Django session源码流程 首先执行的是SessionMiddleware的init方法 import_module(settings.SESSION_ENGINE) 导入了一个 dj ...

  8. 渣渣菜鸡的 ElasticSearch 源码解析 —— 启动流程(上)

    关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/08/11/es-code02/ 前提 上篇文章写了 ElasticSearch 源码解析 -- ...

  9. Django对中间件的调用思想、csrf中间件详细介绍、Django settings源码剖析、Django的Auth模块

    目录 使用Django对中间件的调用思想完成自己的功能 功能要求 importlib模块介绍 功能的实现 csrf中间件详细介绍 跨站请求伪造 Django csrf中间件 form表单 ajax c ...

随机推荐

  1. 用pip install升级已安装的包的附加包, 以tabulate包为例

    用pip install升级已安装的附加包, 以tabulate包为例 去pypi官网查看tabulate包的介绍, 发现tabulate 0.7.6才开始支持宽字符的美化打印. 而且还需要安装它的附 ...

  2. Enumeration和Iterator

    首先,Enumeration已经被Iterator取代了..... Enumeration是个接口,不是类,使用时需要具体的实现类. 里面只定义了两个方法: hasMoreElements()和nex ...

  3. LintCode 35: Reverse Linked List

    LintCode 35: Reverse Linked List 题目描述 翻转一个链表. 样例 给出一个链表1->2->3->null,这个翻转后的链表为3->2->1 ...

  4. Bzoj3352 [ioi2009]旅行商

    Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 89  Solved: 36 Description 旅行商认定如何优化旅行路线是一个非常棘手的计算问题 ...

  5. 2017中国大学生程序设计竞赛 - 网络选拔赛 1005 HDU 6154 CaoHaha's staff (找规律)

    题目链接 Problem Description "You shall not pass!" After shouted out that,the Force Staff appe ...

  6. node.js 基础篇

    日志输出方式 node test.js 2>error.log 1>info.log 如果需要日志文件追加 node test.js 2>>error.log 1>> ...

  7. layui结合SpringMVC上传文件以及携带额外的参数上传文件

    今天在使用layui的过程中,遇到了使用其上传文件的模块.自己感觉文件上传还是bootstrapfileinput插件比较好用一些,灵活方便,bootstrapfileinput使用方法参考:http ...

  8. HTTP::Request 用 add-content 添加 POST参数

    sub MAIN($cmd) { use HTTP::UserAgent; my $r = HTTP::Request.new(); $r.uri: 'http://localhost/a.php'; ...

  9. 移动端测试=== adb 无线连接手机

    无线连接(需要借助 USB 线) 除了可以通过 USB 连接设备与电脑来使用 adb,也可以通过无线连接——虽然连接过程中也有需要使用 USB 的步骤,但是连接成功之后你的设备就可以在一定范围内摆脱 ...

  10. C# 链接webservice报错

    未处理 System.ServiceModel.EndpointNotFoundException  Message="没有终结点对可能接受消息的 http://192.168.0.168/ ...