REST framework 权限管理源码分析

同认证一样,dispatch()作为入口,从self.initial(request, *args, **kwargs)进入initial()

    def initial(self, request, *args, **kwargs):# .......# 用户认证self.perform_authentication(request)# 权限控制self.check_permissions(request)# ...

check_permissions()便是权限管理源码的入口

    # 权限管理def check_permissions(self, request):"""Check if the request should be permitted.Raises an appropriate exception if the request is not permitted."""for permission in self.get_permissions():if not permission.has_permission(request, self):self.permission_denied(request, message=getattr(permission, 'message', None))

和用户认证一样,同样遍历一个权限类对象列表,并且调用该列表中元素的has_permission()方法,该方法返回布尔值,True代表有权限,False代表没有权限.

    def get_permissions(self):return [permission() for permission in self.permission_classes]

如果没有权限,就调用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)

如果使用了REST的认证框架(authentication_classes数组不为空)并且身份认证失败,就抛出NotAuthenticated异常,否则会抛出PermissionDenied异常

class NotAuthenticated(APIException):status_code = status.HTTP_401_UNAUTHORIZEDdefault_detail = _('Authentication credentials were not provided.')default_code = 'not_authenticated'

NotAuthenticated会导致一个401错误(缺少用户凭证)

class PermissionDenied(APIException):status_code = status.HTTP_403_FORBIDDENdefault_detail = _('You do not have permission to perform this action.')default_code = 'permission_denied'

而PermissionDenied会返回错误403(拒绝授权访问)

在向permission_denied()类传递参数时,使用了反射

self.permission_denied(request, message=getattr(permission, 'message', None))

会在这个权限类对象中寻找message属性,没找到就使用None,而这个参数在后来只会被用在PermissionDenied异常上,这些异常都继承自APIException,而在APIException的构造器中,可以发现detail参数就是异常描述,而在自己的权限类中定义message属性可以改变认证失败后的描述

class APIException(Exception):status_code = status.HTTP_500_INTERNAL_SERVER_ERRORdefault_detail = _('A server error occurred.')default_code = 'error'def __init__(self, detail=None, code=None):if detail is None:detail = self.default_detailif code is None:code = self.default_code# ...

示例

# api/utils/Permission.py
from rest_framework.permissions import BasePermissionclass CommonPermission(BasePermission):"""普通用户权限,作用于全局"""def has_permission(self, request, view):print(request.user)if request.user.user_type == 1:return Truedef has_object_permission(self, request, view, obj):"""一旦获得View权限,将获得所有object权限:return: True"""return Trueclass VipPermission(BasePermission):"""VIP 用户权限"""message = '您首先要称为VIP才能访问'def has_permission(self, request, view):print(request.user)if request.user.user_type == 2:return Truedef has_object_permission(self, request, view, obj):return True
# api/view.py
from django.shortcuts import HttpResponse
from django.http import JsonResponse
from rest_framework.views import APIView
from api.utils.Permission import VipPermissionclass LoginView(APIView):authentication_classes = []# 登录无需权限认证permission_classes = []def post(self, request, *args, **kwargs):pass@method_decorator(csrf_exempt, name='dispatch')
class ShopView(APIView):def get(self, request, *args, **kwargs):return HttpResponse(request.user.username)def post(self, request, *args, **kwargs):return HttpResponse('POST')class VipIndexView(APIView):"""只授权给VIP用户查看"""permission_classes = [VipPermission]def get(self, *args, **kwargs):return JsonResponse("welcome VIP ", safe=False)
# RESTdemo.setting.py
REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.MyAuthentication.MyAuthentication'],'UNAUTHENTICATED_USER': None,'UNAUTHENTICATED_TOKEN': None,'DEFAULT_PERMISSION_CLASSES': ['api.utils.Permission.CommonPermission']
}

REST framework 权限管理源码分析相关推荐

  1. linux源码文件名,Linux中文件名解析处理源码分析

    Linux中文件名解析处理源码分析 前言 Linux中对一个文件进行操作的时候,一件很重要的事情是对文件名进行解析处理,并且找到对应文件的inode对象,然后创建表示文件的file对象.在此,对文件名 ...

  2. Android 系统(78)---《android framework常用api源码分析》之 app应用安装流程

    <android framework常用api源码分析>之 app应用安装流程 <android framework常用api源码分析>android生态在中国已经发展非常庞大 ...

  3. 动态代理原理源码分析

    看了这篇文章非常不错转载:https://www.jianshu.com/p/4e14dd223897 Java设计模式(14)----------动态代理原理源码分析 上篇文章<Java设计模 ...

  4. Linux内核 eBPF基础:kprobe原理源码分析:源码分析

    Linux内核 eBPF基础 kprobe原理源码分析:源码分析 荣涛 2021年5月11日 在 <Linux内核 eBPF基础:kprobe原理源码分析:基本介绍与使用>中已经介绍了kp ...

  5. Linux内核 eBPF基础:kprobe原理源码分析:基本介绍与使用示例

    Linux内核 eBPF基础 kprobe原理源码分析:基本介绍与使用示例 荣涛 2021年5月11日 kprobe调试技术是为了便于跟踪内核函数执行状态所设计的一种轻量级内核调试技术. 利用kpro ...

  6. Linux内核 eBPF基础:Tracepoint原理源码分析

    Linux内核 eBPF基础 Tracepoint原理源码分析 荣涛 2021年5月10日 1. 基本原理 需要注意的几点: 本文将从sched_switch相关的tracepoint展开: 关于st ...

  7. 分享一篇glibc 2.30内存管理源码分析

    分享一篇glibc 2.30内存管理源码分析,出于时间关系文章中可能存在问题(如纰漏.或者解释不顺,后续我会持续更新修正),还请大家海涵,大家互相探讨,也多多希望大家指出文章中问题,我及时斧正.本文只 ...

  8. 内存管理源码分析1-ARMV8-AARCH64 MMU 及 linux页表映射过程

    MMU的作用,主要是完成地址的翻译,无论是main-memory地址(DDR地址),还是IO地址(设备device地址),在开启了MMU的系统中,CPU发起的指令读取.数据读写都是虚拟地址,在ARM ...

  9. rt-thread的定时器管理源码分析

    1 前言 rt-thread可以采用软件定时器或硬件定时器来实现定时器管理的,所谓软件定时器是指由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务.而硬件 ...

最新文章

  1. 移动端丨-webkit-overflow-scrolling:touch属性导致页面卡住
  2. 自动调整速率的Actor设计模式
  3. 几种网络负载均衡方法比较
  4. sharepoint ECMA
  5. P2564 [SCOI2009]生日礼物
  6. 前端学习(3075):vue+element今日头条管理-反馈
  7. Fragment:关于Avoid non-default constructors in fragments的错误
  8. Redisson:这么强大的实现分布式锁框架,你还没有?
  9. ubuntu的无比注意事项
  10. 关于预编译和宏定义部分说明
  11. 教妹学Java(十一):操作符简介
  12. HDU 2017 字符串统计(水~)
  13. Python简单版本flappy_bird
  14. Path 贝塞尔曲线 练习 Demo
  15. [小o地图-数据] - 获取全国行政区划轮廓数据(上)
  16. sqlmanager mysql5_SQL Manager for MySQL
  17. stm32单片机实现多个闹钟_基于STM32F103系列单片机的11个定时器解析
  18. 马化腾从CFIDO到QQ(CFIDO BBS回忆录)
  19. 《从案例中学习JavaScript》之实现对话效果
  20. 利用shell求取两个文件的交集、差集、并集等

热门文章

  1. “ 我亦想望,如池鱼悠悠 ... “
  2. illegal to have multiple occurrences of contentType with different values 解决
  3. 关于hexo与github使用过程中的问题与笔记
  4. BZOJ 1567: [JSOI2008]Blue Mary的战役地图
  5. 舒适的路线(codevs 1001)
  6. python3字符串属性(二)
  7. mysql语法替换字符串
  8. java_IO总结(一)
  9. CustomValidator
  10. 用友财务软件主要数据表字段含义