【问题标题】:Django Rest Framework restrict user data view to admins & the very own userDjango Rest Framework 将用户数据视图限制为管理员和自己的用户
【发布时间】:2017-11-15 22:15:21
【问题描述】:

我正在使用 Django 和 DRF,我想检查是否允许用户(普通用户)在通过身份验证后查看其自己的个人资料,并且仅允许查看其个人资料(不允许其他用户)。

serializers.py

class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
    model = User
    fields = ('id', 'url', 'username', 'password', 'email', 'groups', 'is_staff')

def create(self, validated_data):
    user = super().create(validated_data)
    user.set_password(validated_data['password'])
    user.save()
    return user

Views.py

class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
permission_classes = (IsUser,)

permissions.py

class IsUser(permissions.BasePermission):
"""
Custom permission to only allow owners of an object to edit it.
"""

def has_permission(self, request, view, obj):
    # View or Write permissions are only allowed to the owner of the snippet.
    return obj.owner == request.user

这显然是行不通的,因为是错误的。但我不知道如何让用户查看:

http://127.0.0.1:8000/api/users/7

仅当它是管理员或执行请求的同一用户时。

并且: http://127.0.0.1:8000/api/users/ 仅当它是管理员时。

谢谢!

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:
    class UserViewSet(ModelViewSet):
        queryset = Message.objects.all()
        serializer_class = UserSerializer
    
        def get_permissions(self):
            if self.action == 'list':
                self.permission_classes = [IsSuperUser, ]
            elif self.action == 'retrieve':
                self.permission_classes = [IsOwner]
            return super(self.__class__, self).get_permissions()
    
    class IsSuperUser(BasePermission):
    
        def has_permission(self, request, view):
            return request.user and request.user.is_superuser
    
    class IsOwner(permissions.BasePermission):
    
        def has_object_permission(self, request, view, obj):
            if request.user:
                if request.user.is_superuser:
                    return True
                else:
                    return obj.owner == request.user
            else:
                return False
    

    覆盖列表和检索 UserViewSet 的方法可能是最简单的方法。

    【讨论】:

    • 完美运行。非常感谢。
    【解决方案2】:

    我很抱歉,因为我没有足够的代表来添加到 Ykh 的答案中

    views.py

    class UserViewSet(ModelViewSet):
        queryset = Message.objects.all()
        serializer_class = UserSerializer
    
        def get_permissions(self):
            # Overrides to tightest security: Only superuser can create, update, partial update, destroy, list
            self.permission_classes = [IsSuperUser]
    
            # Allow only by explicit exception
            if self.action == 'retrieve':
                self.permission_classes = [IsOwner]
    
            return super().get_permissions()
    

    permissions.py

    from rest_framework.permissions import BasePermission
    
    class IsSuperUser(BasePermission):
    
        def has_permission(self, request, view):
            return request.user and request.user.is_superuser
    
    
    class IsOwner(BasePermission):
    
        def has_object_permission(self, request, view, obj):
            if request.user:
                if request.user.is_superuser:
                    return True
                else:
                    return obj.owner == request.user
            else:
                return False
    

    注意:obj.owner 否则,如果您不是超级用户,您将永远被拒绝。

    感谢 Ykh 的基本回答。

    【讨论】:

      【解决方案3】:

      添加额外的签入IsUser 权限。

      if request.method == permissions.SAFE_METHOD:
          return True
      

      【讨论】:

        【解决方案4】:

        类似示例,默认身份验证列表,仅供超级用户编辑

        from rest_framework.authentication import SessionAuthentication
        from rest_framework.permissions import IsAuthenticated, IsAdminUser
        
        
        class CsrfExemptSessionAuthentication(SessionAuthentication):
            def enforce_csrf(self, request):
                return  # To not perform the csrf check previously happening
        
        
        class OnlyListAvaliableMixin:
            authentication_classes = (CsrfExemptSessionAuthentication,)
        
            def get_permissions(self):
                permission_classes = [IsAuthenticated] if self.action == 'list' else [IsAdminUser] # noqa
                return [permission() for permission in permission_classes]
        
        
        # Example to use
        class ListView(OnlyListAvaliableMixin, viewsets.ModelViewSet, ):
            # premission_classes = (IsAdminUser,)
            queryset = CarMark.objects.all()
            serializer_class = ListViewSerializer
        
        

        【讨论】:

          猜你喜欢
          • 2015-10-07
          • 2015-10-09
          • 2013-04-02
          • 2016-04-04
          • 2019-06-30
          • 1970-01-01
          • 2018-10-24
          • 2020-01-25
          • 2020-05-02
          相关资源
          最近更新 更多