Django自定义权限实现方法及permission_classes装饰器原理解析
DRF 自定义权限实现与 @permission_classes 装饰器原理解析
一、自定义权限实现步骤
DRF 所有权限类都继承自 BasePermission 基类,自定义权限只需要继承该类,重写对应校验方法即可:
- 重写
has_permission(request, view):控制全局视图级别的访问权限,所有请求进入视图前都会先触发该方法校验 - 重写
has_object_permission(request, view, obj):控制单对象级别的访问权限,只有操作单个具体资源(比如查询、修改单条数据)时才会触发该方法校验
示例1:全局视图级权限(仅邮箱验证用户可访问)
from rest_framework.permissions import BasePermission class IsEmailVerified(BasePermission): message = "请先完成邮箱验证" # 自定义权限不通过时的提示信息 def has_permission(self, request, view): return bool( request.user.is_authenticated and request.user.email_verified == True )
示例2:单对象级权限(仅资源所有者可操作)
class IsResourceOwner(BasePermission): message = "你不是该资源的所有者,无权操作" def has_object_permission(self, request, view, obj): # 此处以资源关联的创建用户字段为例,可根据业务自行修改判断逻辑 return obj.create_user == request.user
自定义权限的使用方式
- 全局生效:在
settings.py的REST_FRAMEWORK配置中添加,所有视图默认使用该权限配置REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'your_app.permissions.IsEmailVerified', ] } - 单视图类生效:在视图类中定义
permission_classes属性覆盖全局配置from your_app.permissions import IsResourceOwner from rest_framework.viewsets import ModelViewSet class ArticleViewSet(ModelViewSet): permission_classes = [IsResourceOwner] # 其余视图配置省略 - 函数视图生效:使用
@permission_classes装饰器绑定权限配置from rest_framework.decorators import api_view, permission_classes @api_view(['GET']) @permission_classes([IsEmailVerified]) def get_user_info(request): # 业务逻辑省略
二、@permission_classes 装饰器底层原理
2.1 装饰器本身的核心逻辑
该装饰器的作用非常简单,就是给被装饰的函数视图绑定一个 permission_classes 属性,存储传入的权限类列表,简化后的源码如下:
def permission_classes(classes): def decorator(view_func): view_func.permission_classes = classes return view_func return decorator
2.2 DRF 权限校验的触发逻辑
DRF 处理所有请求时,都会在进入业务逻辑前执行 initial 初始化方法,该方法会按顺序完成身份认证、权限校验、限流校验三步操作,权限校验部分逻辑如下:
- 先从当前视图中提取权限类配置:优先读取视图自身的
permission_classes属性(类视图的类属性、函数视图被装饰器绑定的属性),如果视图没有自定义配置,就读取settings.py中的DEFAULT_PERMISSION_CLASSES配置作为默认值 - 实例化所有权限类,依次调用每个权限类的
has_permission方法,只要有一个权限类返回False,直接抛出 403 异常,终止后续流程 - 如果当前请求是操作单个资源的请求(比如根据ID查询、修改、删除单条数据),会在
has_permission全部校验通过后,继续依次调用每个权限类的has_object_permission方法,同样只要有一个返回False就抛出 403 异常
类视图不需要用装饰器的原因是类本身可以直接定义 permission_classes 类属性,而函数视图无法直接定义类属性,所以需要通过装饰器的方式给函数绑定该属性,DRF 处理类视图和函数视图的权限校验逻辑是完全统一的。
内容的提问来源于stack exchange,提问作者Oussama Eddahri
相关产品推荐
相关产品推荐

