You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义DjangoModelPermissions未生效,如何按组织成员权限限制Widget操作?

问题原因分析

你的权限未生效主要有两个核心问题:

  1. 列表/创建动作未触发组织归属检查:ModelViewSet的list、create等动作仅调用has_permission方法,而你继承的DjangoModelPermissions默认只验证模型级权限(如view_widget),不会检查用户与当前组织的归属关系。
  2. 对象级权限的类型不匹配:obj.organization_id是UUID对象,而request.user.user_organization_ids是字符串列表,直接用in判断会因类型不一致导致匹配失败,本该拦截的请求被错误允许。
修复后的自定义权限类

同时重写has_permission和has_object_permission,覆盖模型级和对象级的权限校验逻辑:

from rest_framework.permissions import DjangoModelPermissions
from rest_framework.exceptions import PermissionDenied

class OrganizationPermission(DjangoModelPermissions):
    def has_permission(self, request, view):
        # 先执行父类的模型权限检查(确保用户拥有对应模型的操作权限)
        has_model_perm = super().has_permission(request, view)
        if not has_model_perm:
            return False
        
        # 从URL参数中获取组织ID,适配你的路由设计
        org_id = view.kwargs.get('organization_id')
        if org_id:
            return org_id in request.user.user_organization_ids
        
        # 处理创建动作:从请求数据中提取组织ID并验证归属
        if request.method == 'POST':
            org_id = request.data.get('organization_id')
            if org_id and org_id in request.user.user_organization_ids:
                return True
            raise PermissionDenied("你无权在该组织下创建资源")
        
        # 无明确组织ID的场景(如全局列表),根据业务需求调整返回逻辑
        return False

    def has_object_permission(self, request, view, obj):
        # 校验对象是否包含组织ID属性
        if not hasattr(obj, 'organization_id') or obj.organization_id is None:
            return False
        
        # 将对象的组织ID转为字符串,与用户的组织ID列表匹配
        obj_org_id = str(obj.organization_id)
        return obj_org_id in request.user.user_organization_ids
额外注意事项
  1. 路由适配:确保你的Widget路由包含organization_id参数,示例如下:
    # urls.py
    from rest_framework.routers import DefaultRouter
    from .views import WidgetViewSet
    
    router = DefaultRouter()
    router.register(r'organizations/(?P<organization_id>[^/.]+)/widgets', WidgetViewSet)
    
  2. 模型权限可选项:如果业务不需要严格的模型级权限(只要用户属于组织就允许操作),可以移除super().has_permission的调用,但保留该逻辑更符合Django权限设计规范。
  3. create动作校验:通过request.data提取组织ID并验证,避免用户在不属于自己的组织下创建Widget。

内容的提问来源于stack exchange,提问作者Joe F.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 16:05:42