翼度科技»论坛 编程开发 python 查看内容

DRF-Permission组件源码分析及改编源码

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
1. 权限组件源码分析

PS:下列源码为了方便理解都进行了简化,只保留了权限相关的代码



由于视图函数中继承了APIView,因此permission_classes可在视图类中进行重写。
注意点:


  • 执行权限校验前,已执行了认证流程。因此此时可通过self.user获取用户对象(认证通过的情况)




2. 实践:编写一个权限类

假设我们在认证通过后,给每个用户对象都加上表示角色的属性role。1代表普通用户, 2代表经理, 3代表BOSS:
  1. import random
  2. from rest_framework.permissions import BasePermission
  3. from rest_framework.request import Request
  4. class UserPermission(BasePermission):
  5.     message = {"code": 1001, "detail": "无权限"}  # 无权限时返回的信息
  6.     def has_permission(self, request, view):
  7.         if request.user.role == 3:
  8.             return True
  9.         return False
  10. class ManagerPermission(BasePermission):
  11.     message = {"code": 1001, "detail": "无权限"}  # 无权限时返回的信息
  12.     def has_permission(self, request, view):
  13.         if request.user.role == 2:
  14.             return True
  15.         return False
  16. class BossPermission(BasePermission):
  17.     message = {"code": 1001, "detail": "无权限"}   # 无权限时返回的信息
  18.     def has_permission(self, request, view):
  19.         if request.user.role == 1:
  20.             return True
  21.         return False
复制代码


3. 源码改编


  • 将权限校验中的“且”改为“或”关系,即只要有一个权限类通过校验即代表权限校验通过,继续执行后续代码:
  1. # 在视图类中重写源码中的check_permissions方法:
  2.     def check_permissions(self, request):
  3.         no_permission_objects = []  # 未通过校验的权限对象
  4.         for permission in self.get_permissions():
  5.             if permission.has_permission(request, self):
  6.                 # 只要有一个权限类通过校验则立即停止函数
  7.                 return
  8.             else:
  9.                 no_permission_objects.append(permission)
  10.         else:   # 所有权限类都未通过校验
  11.             self.permission_denied(
  12.                 request,
  13.                 message=getattr(no_permission_objects[0], 'message', None),  
  14.                 code=getattr(no_permission_objects[0], 'code', None))
复制代码

  • 若想要所有视图类能使用该重写的功能,可将该方法单独写成类(MyAPIView),并继承APIView;其他要使用该重写方法的视图不再继承APIView,而是继承MyAPIView
  1. # utils.py
  2. class MyAPIView(APIView):
  3.     # 改写权限,变为"或"关系;
  4.     def check_permissions(self, request):
  5.         no_permission_objects = []  # 未通过校验的权限对象
  6.         for permission in self.get_permissions():
  7.             if permission.has_permission(request, self):
  8.                 # 只要有一个权限类通过校验则立即停止函数
  9.                 return
  10.             else:
  11.                 no_permission_objects.append(permission)
  12.         else:   # 所有权限类都未通过校验
  13.             self.permission_denied(
  14.                 request,
  15.                 message=getattr(no_permission_objects[0], 'message', None),  
  16.                 code=getattr(no_permission_objects[0], 'code', None))
  17. # views.py
  18. class UserView(APIView):  # 继承DRF的APIView,则权限判断为“且”的关系
  19.     # 只有用户有权限
  20.     permission_classes = [UserPermission]
  21.     def get(self, request, pid):
  22.         return Response("hello get")
  23.     def post(self, request, pid):
  24.         return Response({"nihao  post!"})
  25. class OrderView(MyAPIView):  # 用了自己改写的类MyAPIView,则权限判断为“或"的关系
  26.     # 经理和BOSS都有权限
  27.     permission_classes = [BossPermission, ManagerPermission]
  28.     def get(self, request, pid):
  29.         return Response("hello get")
  30.     def post(self, request, pid):
  31.         return Response({"nihao  post!"})
复制代码
来源:https://www.cnblogs.com/harry6/p/18508623
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具