权限控制是如何实现的?
一般来说, 先有认证才有权限, 也就是用户登录后才能判断其权限, 未登录用户给他一个默认权限.
Django 接收到一个请求, 首先经过权限的检查, 如果通过检查, 拥有访问的权限, 则予以放行, 进入到视图处理. 如果没有通过检查, 不会进入视图层, 直接返回前端相应信息.
使用权限控制
权限控制类:
- class MyPermission(BasePermission):
- message = "您没有权限"
- def has_permission(self, request, view):
- # 判断用户是否有权限, 逻辑自己定义. 返回值为 True 或 False, 代表拥有权限或没有权限
- user_obj = request.user
- if user_obj.type == 3:
- return False
- else:
- return True
- views.py:
- from rest_framework.views import APIView
- from utils.permission import MyPermission
- class TestView(APIView):
- permission_classes = [MyPermission, ] # 使用该权限控制, 可以同时使用多个权限控制类
- def get(self, request, *args, **kwargs):
- pass
- def post(self, request, *args, **kwargs):
- pass
- '''
- 等等一系列的视图功能方法
- '''
全局权限控制:
settings.py
- REST_FRAMEWORK = {
- "DEFAULT_PERMISSION_CLASSES" :['utils.permission.Mypermission',]
- }
注意: 如果有部分类不需要权限判断的话, 可以在 Mypermission 类中添加 "permission_classes = []", 即可
源码分析
其实权限的源码流程跟认证的流程基本相同. 还是要抓住通过源码要想知道什么, 不然就会陷入浩如烟海的源码之中.
1. 为什么会使用 permission_classes 属性变量?
python 的面向对象编程中, 我们首先要执行的方法肯定是 dispatch 方法, 所以我们的分析入口就是 dispatch 方法, 在 dispatch 方法中, 可以看到, 通过 initialize_request 方法将 django 原生的 request 进行了一次封装. 由 initialize_request 方法的实现过程可以看出, 将其封装实例化成了一个 Request 对象. 但权限判断并没有像认证一样初始化到了 Request 对象中, 但对 django 原生的 request 封装还是需要强调的, 因为编写代码的过程中对 django 原生的 request 的使用是必不可免的.
同样的, 权限判断的具体过程跟认证一样, 也是在 dispatch 方法中所调用的 initial 方法中实现. 再跳转到 initial 方法中去.
在 initial 方法中, 可以看到权限判断的方法, 没错, 就是通过 check_permissions 方法实现的. 再跳转到这个方法中去.
在 check_permissions 方法中, 就可以看到权限的判断就是通过这个 for 循环实现的. 正因为在业务代码中可能存在若干种类型的权限判断, 所以才会通过循环去执行我们定义好的权限判断类来完成多个权限体系的判断功能. 这样, 我们可以感觉到这里的 "self.get_permissions()" 的返回值应该就是我们在视图类中赋值过的 permissions_classes 属性变量的值. 那就跳转到这个方法中去看看吧.
在 get_permissions 方法中看到, 跟认证一样, 返回值同样是一个列表生成式, 而这个列表生成式使用的属性变量正是我们赋值过的 permission_classes, 跟我们之前的猜测完全一致. 综上所述, 我们为了让 drf 接口源码使用上我们自己定义的权限判断类, 那我们就必须按照源码中写的借口, 将 permission_classes 属性变量赋值
2. 在权限判断类中为什么会定义一个名称为 has_permission 的方法?
回到 check_permissions 方法中, 我们看 if 判断句, 前面刚刚说过, 在 for 中的 permission 其实就是我们自己定义的权限判断类, 那么在 if 句中的 ".has_permission(request,self)" 不就应该就是 Mypermission 类中的方法吗? 所以, 我们自己定义的 Mypermission 类中一定要实现 has_permission 这个方法.(要注意这个方法的参数)
3.has_permission 方法中, 为什么返回值为布尔值?
还是跟上一个问题一样的, 在上图中的 if 句中, 我们可以看到 "permission.has_permission(request, self)" 的返回值不就是布尔值吗, 这个返回值不就是 has_permission 方法返回值吗? 当返回值为 False 时, 就会执行 if 句中的代码, 来抛出异常.
来源: https://www.cnblogs.com/V587Chinese/p/11607881.html