在API中添加权限 – Django REST框架
谈到访问控制,有许多不同的情况需要考虑。允许未经授权的人访问有风险的操作或受限制的区域会导致巨大的漏洞。这突出了在API中添加权限的重要性。
Django REST框架允许我们利用权限来定义哪些内容可以被访问,哪些动作可以以有意义的或通用的方式执行。权限检查总是在每个视图的开始运行。它使用 “request.user “和 “request.auth “属性中的认证信息来处理每个传入的请求。如果权限检查失败,那么视图代码将不会运行。
注意:与认证一起,权限决定了对一个传入的请求是授予还是拒绝访问。在本节中,我们将结合基本认证和Django REST框架的权限来设置访问控制。你可以参考Django REST框架中模型、序列化器和视图的可浏览API
让我们深入挖掘一下Django REST框架的权限。
- AllowAny
- IsAuthenticated
- IsAdminUser
- IsAuthenticatedOrReadOnly
- DjangoModelPermissions
- DjangoModelPermissionsOrAnonReadOnly
- DjangoObjectPermissions
AllowAny
AllowAny权限类将允许不受限制的访问,不管请求是经过认证还是未经认证的。这里的权限设置默认为不受限制的访问
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
]
你不需要设置这个权限,但建议你提一下,以明确这个意图。除了在全局范围内提到它,你可以在每个视图的基础上设置权限策略。如果你使用的是基于APIView类的视图,代码如下
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)
在使用@api_view装饰器和基于函数的视图时,代码如下
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
IsAuthenticated权限类拒绝未经认证的用户使用API进行任何操作。这确保了API只对注册用户开放。让我们在我们的RESTful Web服务中使用IsAuthenticated类。在这里,我们可以在每个视图的基础上设置权限策略。让我们在我们的RobotDetail和RobotList类中导入并添加权限类。代码如下。
from rest_framework.permissions import IsAuthenticated
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的命令是
http :8000/robot/
输出
由于我们没有提供任何认证细节,API拒绝了检索机器人细节的请求。现在我们将使用Django的交互式外壳创建一个新的用户,并尝试使用证书的HTTPie命令。
注意:你可以参考文章《使用Django的交互式外壳为Django创建一个用户》。
HTTPie的命令如下。
http -a “sonu”:”sn@pswrd” :8000/robot/
输出
让我们尝试一下HTTPie命令,创建一个新的机器人条目。
http -a “sonu”:”sn@pswrd” POST :8000/robot/ name=”IRB 1100″ robot_category=”Articulated Robots” currency=”USD” price=25000 manufacturer=”ABB” manufacturing_date=”2020-05-10 00:00:00+00:00″
输出
IsAdminUser
IsAdminUser权限类将允许权限给user.is_staff为True的用户。这个权限类可以确保受信任的管理员可以访问API。让我们来使用IsAdminUser权限类。让我们导入这个权限类
from rest_framework.permissions import IsAdminUser
你可以用以下代码替换RobotDetail和RobotList类。
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的命令是
http -a “sonu”:”sn@pswrd” :8000/robot/
输出
你可以注意到消息说 “你没有权限执行这个动作”。这是因为该用户不是管理员。让我们提供我们的超级管理员凭证。HTTPie的命令是
http -a “admin”:”admin@123″ :8000/robot/
输出
IsAuthenticatedOrReadOnly
IsAuthenticatedOrReadOnly权限类允许非授权用户执行安全的方法,而认证用户可以执行任何操作。当我们需要为匿名用户设置读取权限,为认证用户设置读/写权限时,这个类很有用。让我们来导入权限类
from rest_framework.permissions import IsAuthenticatedOrReadOnly
现在,你可以用以下代码替换RobotDetail和RobotList类。
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的命令如下。
http :8000/robot/
输出
现在,让我们尝试创建一个新的机器人,而不提供凭证。HTTPie的命令如下。
http POST :8000/robot/ name=”IRB 120″ robot_category=”Articulated Robots” currency=”USD” price=35000 manufacturer=”ABB” manufacturing_date=”2020-08-10 00:00:00+00:00″
输出
IsAuthenticatedOrReadOnly权限类只允许对未认证的用户进行安全操作。让我们通过提供用户凭证来创建一个新的机器人。
http -a “sonu”:”sn@pswrd” POST :8000/robot/ name=”IRB 120″ robot_category=”Articulated Robots” currency=”USD” price=35000 manufacturer=”ABB” manufacturing_date=”2020-08-10 00:00:00+00:00″
输出
DjangoModelPermissions
在DjangoModelPermissions类中,只有当用户被认证并分配了相关的模型权限时,才会被授予认证。模型权限如下
- 用户必须在模型上有添加权限才能提出POST请求。
- 用户必须在模型上有改变的权限才能提出PUT和PATCH请求。
- 用户必须在模型上有删除权限才能提出DELETE请求。
默认情况下,该类允许已认证用户的GET请求。DjangoModelPermissions类与Django的标准django.contrib.auth模型权限相联系。它必须只应用于有.queryset属性或get_queryset()方法的视图。
你可以导入DjangoModelPermissions类。
from rest_framework.permissions import DjangoModelPermissions
接下来,用以下代码替换RobotDetail和RobotList类。
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的命令如下。
http -a “sonu”:”sn@pswrd” POST :8000/robot/ name=”IRB 140″ robot_category=”Articulated Robots” currency=”USD” price=35000 manufacturer=”ABB” manufacturing_date=”2021-01-10 00:00:00+00:00″
输出
你可以注意到,创建一个机器人的权限被拒绝了。这是因为我们还没有为给定的用户设置模型级权限。要设置添加机器人的权限,你可以通过管理面板以超级用户的身份登录,并在用户部分选择用户来添加权限。最后,保存更改。分享下面的屏幕截图。
让我们再试一下同样的HTTPie命令。
http -a “sonu”:”sn@pswrd” POST :8000/robot/ name=”IRB 140″ robot_category=”Articulated Robots” currency=”USD” price=35000 manufacturer=”ABB” manufacturing_date=”2021-01-10 00:00:00+00:00″
输出
DjangoModelPermissionsOrAnonReadOnly
DjangoModelPermissionsOrAnonReadOnly权限类与DjangoModelPermissions类相同,只是它允许未经认证的用户对API有只读访问权。
我们来导入DjangoModelPermissionsOrAnonReadOnly类。
from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
现在你可以将权限类添加到RobotDetail和RobotList类。代码如下。
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的命令如下。
http :8000/robot/
输出
DjangoObjectPermissions
DjangoObjectPermissions允许模型上的每个对象权限,它可以为表中的个别行(模型实例)设置权限。用户必须经过认证才能获得授权,并且应该被分配相关的每对象权限和相关的模型权限。为了设置相关的每个对象的权限,我们需要对DjangoObjectPermissions进行子类化并实现has_object_permission()方法。相关的模型权限如下。
- 用户必须在模型上有添加权限才能提出POST请求。
- 用户必须在模型上有改变的权限才能提出PUT和PATCH请求。
- 用户必须在模型上有删除权限才能提出DELETE请求。
通过DjangoModelPermissions,你可以通过覆盖DjangoObjectPermissions来创建自定义模型权限。你可以查看Django REST框架中的自定义对象级权限。