📌  相关文章
📜  在 API 中添加权限 – Django REST Framework

📅  最后修改于: 2022-05-13 01:54:19.828000             🧑  作者: Mango

在 API 中添加权限 – Django REST Framework

在访问控制方面,有许多不同的场景需要考虑。允许未经授权访问危险操作或限制区域会导致巨大的漏洞。这突出了在 API 中添加权限的重要性。

Django REST 框架允许我们利用权限来定义可以访问的内容以及可以以有意义或通用的方式执行的操作。权限检查始终在每个视图的开头运行。它为每个传入请求使用“request.user”和“request.auth”属性中的身份验证信息。如果权限检查失败,则视图代码将不会运行。

注意:权限与身份验证一起确定是授予还是拒绝传入请求的访问权限。在本节中,我们将结合基本身份验证和 Django REST 框架权限来设置访问控制。您可以参考 Django REST Framework for Models、Serializers 和 Views 中的 Browsable API

让我们深入研究 Django REST 框架权限。

  • 允许任何
  • 已认证
  • 是管理员用户
  • 是认证的还是只读的
  • DjangoModelPermissions
  • DjangoModelPermissionsOrAnonReadOnly
  • Django 对象权限

允许任何

AllowAny 权限类将允许不受限制的访问,无论请求是经过身份验证还是未经身份验证。这里的权限设置默认为无限制访问



'DEFAULT_PERMISSION_CLASSES': [
   'rest_framework.permissions.AllowAny',
]

您不需要设置此权限,但建议提及它以明确意图。除了全局提及之外,您还可以在每个视图的基础上设置权限策略。如果使用的是APIView类的视图,代码如下

Python3
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
  
class ClassBasedView(APIView):
    permission_classes = [AllowAny]
  
    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)


Python3
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
  
@api_view(['GET'])
@permission_classes([AllowAny])
def function_view(request, format=None):
    content = {
        'status': 'request was permitted'
    }
    return Response(content)


Python3
class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'
  
  
class RobotList(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'


Python3
class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAdminUser]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'
  
  
class RobotList(generics.ListCreateAPIView):
    permission_classes = [IsAdminUser]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'


Python3
class RobotList(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticatedOrReadOnly]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list' 
  
class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAuthenticatedOrReadOnly]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'


Python3
class RobotList(generics.ListCreateAPIView):
    permission_classes = [DjangoModelPermissions]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'
  
class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [DjangoModelPermissions]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'


Python3
class RobotList(generics.ListCreateAPIView):
    permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'
  
class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'


在基于函数的视图中使用@api_view 装饰器时,代码如下

蟒蛇3

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
  
@api_view(['GET'])
@permission_classes([AllowAny])
def function_view(request, format=None):
    content = {
        'status': 'request was permitted'
    }
    return Response(content)

已认证

IsAuthenticated 权限类拒绝未经身份验证的用户使用 API 进行任何操作。这确保了 API 仅对注册用户可访问。让我们在 RESTful Web 服务中使用 IsAuthenticated 类。在这里,我们可以在每个视图的基础上设置权限策略。让我们导入并添加权限类 在我们的 RobotDetail 和 RobotList 类中。代码如下:

from rest_framework.permissions import IsAuthenticated

蟒蛇3

class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'
  
  
class RobotList(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'

让我们尝试在不提供任何凭据的情况下检索机器人。 HTTPie 命令是

输出

由于我们尚未提供任何身份验证详细信息,因此 API 已拒绝检索机器人详细信息的请求。现在我们将使用 Django 的交互式 shell 创建一个新用户,并使用凭据尝试 HTTPie 命令。

注意:您可以参考文章使用 Django 的交互式 Shell 为 Django 创建用户。

HTTPie 命令如下:

输出

让我们尝试一个创建新机器人条目的 HTTPie 命令。

输出

是管理员用户

IsAdminUser 权限类将允许 user.is_staff 为 True 的用户获得权限。此权限类别可确保受信任的管理员可以访问 API。让我们使用 IsAdminUser 权限类。让我们导入权限类

from rest_framework.permissions import IsAdminUser

您可以使用以下代码替换 RobotDetail 和 RobotList 类。

蟒蛇3

class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAdminUser]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'
  
  
class RobotList(generics.ListCreateAPIView):
    permission_classes = [IsAdminUser]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'

现在让我们尝试提供普通用户凭据。 HTTPie 命令是

输出

您会注意到“您无权执行此操作”的消息。这是因为用户不是管理员。让我们提供我们的超级管理员凭据。 HTTPie 命令是



输出

是认证的还是只读的

IsAuthenticatedOrReadOnly 权限类允许未经授权的用户执行安全的方法,而经过身份验证的用户可以执行任何操作。当我们需要为匿名用户设置读权限和为经过身份验证的用户设置读/写权限时,这个类很有用。让我们导入权限类

from rest_framework.permissions import IsAuthenticatedOrReadOnly

现在,您可以使用以下代码替换 RobotDetail 和 RobotList 类。

蟒蛇3

class RobotList(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticatedOrReadOnly]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list' 
  
class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAuthenticatedOrReadOnly]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'

让我们尝试在不提供任何凭据的情况下检索机器人详细信息。 HTTPie 命令如下:

输出



现在让我们尝试在不提供凭据的情况下创建一个新机器人。 HTTPie 命令如下:

输出

IsAuthenticatedOrReadOnly 权限类只允许未经身份验证的用户进行安全操作。让我们通过提供用户凭据来创建一个新机器人。

输出

DjangoModelPermissions

在 DjangoModelPermissions 类中,仅当用户通过身份验证并分配了相关模型权限时才授予身份验证。模型权限如下

  • 用户必须具有添加 允许模型发出 POST 请求。
  • 用户必须具有模型的更改权限才能发出 PUT 和 PATCH 请求。
  • 用户必须具有模型的删除权限才能发出 DELETE 请求。

默认情况下,该类允许对经过身份验证的用户进行 GET 请求。 DjangoModelPermissions 类与 Django 的标准django.contrib.auth模型权限相关联。它只能应用于具有 .queryset 属性或 get_queryset() 方法的视图。

您可以导入 DjangoModelPermissions 类。

from rest_framework.permissions import DjangoModelPermissions

接下来,用以下代码替换 RobotDetail 和 RobotList 类。

蟒蛇3

class RobotList(generics.ListCreateAPIView):
    permission_classes = [DjangoModelPermissions]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'
  
class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [DjangoModelPermissions]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'

让我们尝试通过提供用户凭据来创建机器人。 HTTPie 命令如下:

输出

您可以注意到,创建机器人的权限被拒绝。这是因为我们尚未为给定用户设置模型级权限。要设置添加机器人的权限,您可以通过管理面板以超级用户身份登录,并通过在“用户”部分下选择用户来添加权限。最后,保存更改。下面分享截图:

让我们再试一次相同的 HTTPie 命令。



输出

DjangoModelPermissionsOrAnonReadOnly

DjangoModelPermissionsOrAnonReadOnly 权限类与 DjangoModelPermissions 类相同,只是它允许未经身份验证的用户对 API 具有只读访问权限。

让我们导入 DjangoModelPermissionsOrAnonReadOnly 类。

from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly

现在您可以将权限类添加到 RobotDetail 和 RobotList 类。代码如下:

蟒蛇3

class RobotList(generics.ListCreateAPIView):
    permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'
  
class RobotDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-detail'

让我们尝试在不提供任何凭据的情况下检索机器人。 HTTPie 命令如下:

输出

Django 对象权限

DjangoObjectPermissions 允许对模型的每个对象权限,它可以为表(模型实例)中的单个行设置权限。用户必须经过身份验证才能授予授权,并且应该被分配相关的每个对象权限和相关的模型权限。要设置相关的每个对象权限,我们需要继承 DjangoObjectPermissions 并实现 has_object_permission() 方法。相关模型权限如下:

  • 用户必须具有模型的添加权限才能发出 POST 请求。
  • 用户必须具有模型的更改权限才能发出 PUT 和 PATCH 请求。
  • 用户必须具有模型的删除权限才能发出 DELETE 请求。

使用 DjangoModelPermissions,您可以通过覆盖 DjangoObjectPermissions 来创建自定义模型权限。您可以在 Django REST Framework 中检查自定义对象级别权限。