Django API 权限装饰器

Posted

技术标签:

【中文标题】Django API 权限装饰器【英文标题】:Django API permission decorator 【发布时间】:2021-07-25 08:18:52 【问题描述】:

目标: 我想只允许具有特定权限的用户使用某些端点。

例如调用允许创建用户的端点,您需要权限“user.create”

问题:

我尝试创建一个中间件以将其与 decorator_from_middleware_with_args

一起使用
class PermissionMiddleware:

def __init__(self, view,permission):
    self.permission = permission

def process_request(self, request):
    if not request.user.has_perm(permission_name):
        if raise_exception:
            raise exceptions.PermissionDenied("Don't have permission")
        return False
    return True

然后在我的视图中我使用 decorator_from_middleware_with_args

class UtilisateurViewSet(viewsets.ViewSet):
permission = decorator_from_middleware_with_args(PermissionMiddleware)

@permission('view_utilisateur')
def list(self, request):
    queryset = Utilisateur.objects.all()
    serializer = UtilisateurSerializer(queryset, many=True)
    return Response(serializer.data)

但是当我调用端点时出现错误:

AttributeError: 'UtilisateurViewSet' 对象没有属性 'user'

我认为是因为 django.contrib.sessions.middleware.SessionMiddleware 还没有执行。

有没有办法定义中间件的顺序,或者其他方式来实现想要的?

【问题讨论】:

因此,中间件的顺序与 settings.py 中 MIDDLEWARES 中列出的顺序完全相同。你试过向上移动 SessionMiddleware 吗? 其实为什么需要使用装饰器呢?您可以使用permission_classes,但在您的类的 has_permission 方法中检查特定方法(GET、POST 等) 我尝试将 SessionMiddleware 放在首位,但它没有任何改变,我也尝试使用 permission_classes 但我必须为每个模型创建一个权限类?使用装饰器定义权限会更容易。 如果我不能使用装饰器,我会使用permission_classes 并为每个模型创建一个类,但我更愿意让装饰器工作 你也可以定义一个工厂,它会返回一个根据你的权限生成的新类***.com/questions/52888339/… 【参考方案1】:

我没有找到如何做我想要的,但我确实以其他方式实现了它。

我使用permission_classes 并在一个类中定义了所需的权限,我将为我要添加的每个视图集执行此操作。

class UtilisateurPermission(permissions.BasePermission):
def has_permission(self, request, view):
    if view.action == "create":
        return bool(request.user.is_authenticated and (request.user.is_superuser or request.user.has_perm("utilisateur_create")))
    elif view.action == "retrieve":
        return bool(request.user.is_authenticated and (request.user.is_superuser or request.user.has_perm("utilisateur_retrieve")))
    elif view.action == "list":
        return bool(request.user.is_authenticated and (request.user.is_superuser or request.user.has_perm("utilisateur_list")))
    elif view.action == "destroy":
        return bool(request.user.is_authenticated and (request.user.is_superuser or request.user.has_perm("utilisateur_destroy")))
    elif view.action == "archive":
        return bool(request.user.is_authenticated and (request.user.is_superuser or request.user.has_perm("utilisateur_archive")))
    elif view.action in ['update', 'partial_update']:
        return bool(request.user.is_authenticated and (request.user.is_superuser or request.user.has_perm("utilisateur_update")))
    else:
        return False

【讨论】:

以上是关于Django API 权限装饰器的主要内容,如果未能解决你的问题,请参考以下文章

django权限验证装饰器

Django is_staff 权限装饰器

装饰器 以及 django 中的应用

django的权限认证:登录和退出。auth模块和@login_required装饰器

19Django开发总结:自带的常用装饰器应用场景及正确使用方法总结

在django中应用装饰器