如何限制经过身份验证的用户代表他人发帖?

时间:2019-04-29 20:00:46

标签: django django-models django-rest-framework

如果我以user1的身份登录并且正在访问名为ViewSet的{​​{1}},则RecipeSubmissionViewSet会提取用户想要的食谱的POST提交。假设recipe_id模型上有一个user1字段,并且我可以将其与request.user进行比较,如何确保user2不提交Recipe的食谱?我应该为此使用权限类还是有更好的方法?我是从后端的角度讲的,没有考虑到前端当然会过滤掉属于用户的食谱,而只会向他们展示自己的食谱。

3 个答案:

答案 0 :(得分:2)

可以有两种方法。您可以过滤掉查询集或定义权限类。

如果您这样重写get_queryset方法。

class RecipeSubmissionViewSet(...):
    def get_queryset(self):
        return Recipe.objects.filter(owner=self.request.user)
        # you can also use filtration based on action name like this

        # if self.action == 'update':
        #      return Recipe.objects.filter(owner=self.request.user)
        # return Recipe.objects.all()

用户将获得 404 响应,并且将永远无法访问自己拥有的对象。

第二选择是权限等级。您可以定义自定义权限类,并像这样显式检查所有权。

from rest_framework.permissions import BasePermission

class RecipeSubmissionPermission(BasePermission):
    def has_object_permission(self, request, view, obj):
        # you can also check permission here based on action
        # if view.action == 'update':
        #    pass
        return request.user.is_authenticated and obj.owner == request.user




class RecipeSubmissionViewSet(...):
    permission_classes=[RecipeSubmissionPermission]

在这种情况下,用户将获得 403 权限错误。

如果同时使用这两种方法。首选 404

您可以使用任意一种方法,也可以同时使用这两种方法。权限类看起来更像是编程的和结构化的方式,但是用户将知道具有此ID的对象存在,但他没有权限对其进行更新。但是,如果您覆盖查询集,则用户甚至无法知道对象是否存在,因此更加安全。

答案 1 :(得分:0)

您是否正在使用django身份验证系统?然后,您应该能够在视图中访问request.user并相应地设置owner字段。

编辑:我想我误解了这个问题。

但是this可以提供帮助,Nafees Anwar看起来不错。

答案 2 :(得分:0)

Nafees的答案几乎可以解决。

我一直在开发对用户具有多租户的微服务,针对它们的规则(根据我的项目规范)是:

  • 用户不能代表其他公司/用户创建项目
  • 用户无法查看/编辑属于另一家公司的项目。

我这样做的方法很简单。

禁止查看/编辑他人的东西

def get_queryset(self):
    return self.queryset.filter(user=request.user)

并且为了禁止编辑其他人的东西,这是在序列化器上完成的

class SomeSerializer(...):
    def validate(self, data):
        data.pop('user', None)
        data['user'] = self.context['request'].user

使用上述方法,如果user1请求user2信息,则视图集中的get_queryset将始终返回404。

validate函数将阻止分配。就是如果user1创建了一个分配给user2的东西,而是分配了user1,这就是我在应用程序中需要的行为,那么如果需要,您可以始终raise serializers.ValidationError("You cannot assign stuff to user2")代替,而不是像我在用例中那样重新分配用户。通过在validate中使用此逻辑,您可以确保任何可写函数对于该序列化器始终具有相同的行为。

希望这会有所帮助。