权限-Django REST框架
permissions.py
权限
身份验证或标识本身通常不足以访问信息或代码。为此,请求访问的实体必须具有授权。
— Apple Developer文档
连同认证和节流,权限决定是否应授予或拒绝访问请求。
权限检查总是在视图开始时运行,然后才允许进行任何其他代码。权限检查通常使用request.user
和request.auth
属性来确定是否应该允许传入请求。
权限用于授予或拒绝对不同类别的用户访问API的不同部分。
最简单的权限方式是允许访问任何经过身份验证的用户,并拒绝对任何未经身份验证的用户的访问。这对应于IsAuthenticated
类在REST框架中。
一种稍微不那么严格的权限方式是允许对经过身份验证的用户进行完全访问,但允许对未经身份验证的用户进行只读访问。这对应于IsAuthenticatedOradOnly
类在REST框架中。
如何确定权限
REST框架中的权限总是定义为权限类的列表。
在运行视图的主体之前,将检查列表中的每个权限。如果任何权限检查失败,则exceptions.PermissionDenied
或exceptions.NotAuthenticated
将引发异常,并且视图的主体将不会运行。
当权限检查失败时,将根据以下规则返回“403禁止”或“401未经授权”响应:
- 请求已成功验证,但权限被拒绝。-将返回HTTP 403禁止响应。
- 请求未被成功验证,最高优先级身份验证类也未成功验证。不使用
WWW-Authenticate
标题。-将返回HTTP 403禁止响应。 - 请求未被成功验证,最高优先级身份验证类也未成功验证。是吗?使用
WWW-Authenticate
标题。-HTTP 401未经授权的响应,并提供适当的WWW-Authenticate
将返回标头。
对象级权限
REST框架权限还支持对象级权限。对象级权限用于确定是否应该允许用户对特定对象(通常是模型实例)进行操作。
对象级权限由REST框架的泛型视图在.get_object()
叫做。与视图级权限一样,exceptions.PermissionDenied
如果不允许用户对给定对象执行操作,则将引发异常。
如果您正在编写自己的视图并希望强制执行对象级别的权限,或者如果您重写了get_object
方法,则需要显式调用.check_object_permissions(request, obj)
方法在检索对象时对视图进行处理。
这要么会引发PermissionDenied
或NotAuthenticated
异常,或者如果视图具有适当的权限,则直接返回。
例如:
def get_object(self):obj = get_object_or_404(self.get_queryset(), pk=self.kwargs["pk"])self.check_object_permissions(self.request, obj)return obj
注*除DjangoObjectPermission
中提供的权限类。rest_framework.permissions
不要实现检查对象权限所需的方法。
如果希望使用提供的权限类来检查对象权限,你必须子类并实现has_object_permission()
中描述的方法。自定义权限第一节(下文)。
对象级权限的限制
由于性能原因,泛型视图在返回对象列表时不会自动将对象级权限应用于查询集中的每个实例。
通常,当您使用对象级权限时,您也会希望过滤查询集适当地,以确保用户只对允许查看的实例具有可见性。
设置权限策略
默认权限策略可以全局设置,使用DEFAULT_PERMISSION_CLASSES
背景。例如。
REST_FRAMEWORK = {'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated',]
}
如果未指定,则此设置默认为允许不受限制的访问:
'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.AllowAny',
]
还可以使用APIView
基于类的视图。
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIViewclass ExampleView(APIView):permission_classes = [IsAuthenticated]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 IsAuthenticated
from rest_framework.response import Response@api_view(['GET'])
@permission_classes([IsAuthenticated])
def example_view(request, format=None):content = {'status': 'request was permitted'}return Response(content)
注:通过class属性设置新权限类时,您是在告诉视图忽略设置在settings.py档案。
只要他们继承了rest_framework.permissions.BasePermission
,权限可以使用标准Python按位运算符组合。例如,IsAuthenticatedOradOnly
可以写成:
from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
from rest_framework.views import APIViewclass ReadOnly(BasePermission):def has_permission(self, request, view):return request.method in SAFE_METHODSclass ExampleView(APIView):permission_classes = [IsAuthenticated|ReadOnly]def get(self, request, format=None):content = {'status': 'request was permitted'}return Response(content)
注:它支持&(和)、(或)和~(不)。
API参考
AllowAny
这个AllowAny
权限类将允许不受限制的访问,无论请求是经过身份验证还是未经身份验证.
严格来说,此权限并不是必需的,因为您可以通过对权限设置使用空列表或元组来实现相同的结果,但是您可能会发现指定这个类很有用,因为它使意图显式化。
IsAuthenticated
这个IsAuthenticated
权限类将拒绝任何未经身份验证的用户的权限,否则将允许权限。
如果您希望您的API仅供注册用户访问,则此权限是合适的。
IsAdminUser
这个IsAdminUser
类将拒绝任何用户的权限,除非user.is_staff
是True
在这种情况下,将允许许可。
如果您希望您的API仅供受信任管理员的子集访问,则此权限是合适的。
IsAuthenticatedOradOnly
这个IsAuthenticatedOradOnly
将允许经过身份验证的用户执行任何请求。只有当请求方法是“安全”方法之一时,才允许向未经授权的用户提出请求;GET
, HEAD
或OPTIONS
.
如果您希望API允许匿名用户的读取权限,并且只允许对经过身份验证的用户使用写权限,则此权限是合适的。
DjangoModelPermission
这个权限类与Django的标准相关联django.contrib.auth
模型权限...此权限只能应用于具有.queryset
属性集只有在用户被认证并且有相关模型权限分配。
-
POST
请求要求用户拥有add
对模型的许可。 -
PUT
和PATCH
请求要求用户拥有change
对模型的许可。 -
DELETE
请求要求用户拥有delete
对模型的许可。
还可以重写默认行为以支持自定义模型权限。例如,您可能希望包括view
模型权限GET
请求。
若要使用自定义模型权限,请重写DjangoModelPermission
并设置.perms_map
财产。有关详细信息,请参阅源代码。
与不包括queryset
属性。
如果使用此权限的视图使用重写的get_queryset()
方法可能没有queryset
属性在视图上。在本例中,我们还建议使用一个哨兵查询集来标记视图,以便该类可以确定所需的权限。例如:
queryset = User.objects.none() # Required for DjangoModelPermissions
DjangoModelPermissionsOrAnonReadly
类似于DjangoModelPermission
,但也允许未经身份验证的用户对api进行只读访问。
DjangoObjectPermission
这个权限类与Django的标准相关联对象权限框架它允许模型上的每个对象的权限。为了使用这个权限类,还需要添加一个支持对象级权限的权限后端,例如Django-监护人.
同.一样DjangoModelPermission
,此权限只能应用于具有.queryset
财产或.get_queryset()
方法。只有在用户被认证并且有相关的每个对象的权限和相关模型权限分配。
-
POST
请求要求用户拥有add
对模型实例的权限。 -
PUT
和PATCH
请求要求用户拥有change
对模型实例的权限。 -
DELETE
请求要求用户拥有delete
对模型实例的权限。
请注意DjangoObjectPermission
不要求Django-监护人
包,并且应该同样支持其他对象级后端。
同.一样DjangoModelPermission
可以通过重写自定义模型权限。DjangoObjectPermission
并设置.perms_map
财产。有关详细信息,请参阅源代码。
注*如果需要对象级别view
对.的权限GET
, HEAD
和OPTIONS
请求并正在使用Django-卫士作为对象级权限后端,您需要考虑使用DjangoObjectPermissionsFilter
类提供的djangorestframework-guardian
包装...它确保列表端点只返回结果,包括用户具有适当视图权限的对象。
自定义权限
若要实现自定义权限,请重写BasePermission
并实现以下方法之一或两者之一:
.has_permission(self, request, view)
.has_object_permission(self, request, view, obj)
方法应该返回True
如果请求应被授予访问权,以及False
不然的话。
如果需要测试请求是读操作还是写操作,则应对照常量检查请求方法。SAFE_METHODS
,它是一个包含以下内容的元组'GET'
, 'OPTIONS'
和'HEAD'
...例如:
if request.method in permissions.SAFE_METHODS:# Check permissions for read-only request
else:# Check permissions for write request
注*实例级has_object_permission
方法将只在视图级别的情况下调用。has_permission
支票已经通过了。还请注意,为了运行实例级检查,视图代码应该显式地调用.check_object_permissions(request, obj)
...如果使用的是泛型视图,则默认情况下将为您处理。(基于函数的视图将需要显式检查对象权限,从而引发PermissionDenied
(关于失败。)
自定义权限将引发PermissionDenied
如果测试失败,则为例外。若要更改与异常关联的错误消息,请实现message
属性直接放在自定义权限上。否则default_detail
属性PermissionDenied
会被使用。
from rest_framework import permissionsclass CustomerAccessPermission(permissions.BasePermission):message = 'Adding customers not allowed.'def has_permission(self, request, view):...
实例
下面是一个权限类的示例,该类根据黑名单检查传入请求的IP地址,如果IP已被列入黑名单,则拒绝该请求。
from rest_framework import permissionsclass BlacklistPermission(permissions.BasePermission):"""Global permission check for blacklisted IPs."""def has_permission(self, request, view):ip_addr = request.META['REMOTE_ADDR']blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()return not blacklisted
除了针对所有传入请求运行的全局权限之外,还可以创建对象级权限,这些权限只针对影响特定对象实例的操作运行。例如:
class IsOwnerOrReadOnly(permissions.BasePermission):"""Object-level permission to only allow owners of an object to edit it.Assumes the model instance has an `owner` attribute."""def has_object_permission(self, request, view, obj):# Read permissions are allowed to any request,# so we'll always allow GET, HEAD or OPTIONS requests.if request.method in permissions.SAFE_METHODS:return True# Instance must have an attribute named `owner`.return obj.owner == request.user
请注意,泛型视图将检查适当的对象级别权限,但如果您正在编写自己的自定义视图,则需要确保检查对象级别的权限。您可以通过调用self.check_object_permissions(request, obj)
从视图中获得对象实例后。这一呼吁将提出一个适当的APIException
如果任何对象级权限检查失败,否则只会返回.
还请注意,泛型视图将只检查检索单个模型实例的视图的对象级权限。如果需要对列表视图进行对象级筛选,则需要分别对查询集进行筛选。见过滤文档更多细节。
第三方包
下面的第三方包也是可用的。
DRF-访问策略
这个Django REST-访问策略包提供了一种在附加到视图集或基于函数的视图的声明性策略类中定义复杂访问规则的方法。这些策略是在JSON中以类似于AWS的标识和访问管理策略的格式定义的。
组合权限
这个组合权限包提供了一种简单的方法,可以使用小型和可重用的组件来定义复杂和多深度(带有逻辑运算符)权限对象。
休息状态
这个休息状态包是以简单方便的方式构建复杂权限的另一个扩展。扩展允许您将权限与逻辑运算符组合在一起。
干REST权限
这个干REST权限包提供了为单个默认操作和自定义操作定义不同权限的能力。此包用于具有从应用程序数据模型中定义的关系派生出来的权限的应用程序。它还支持通过API的序列化程序将权限检查返回给客户端应用程序。此外,它还支持向默认列表操作和自定义列表操作添加权限,以限制它们为每个用户检索的数据。
Django REST框架角色
这个Django REST框架角色包使得在多种类型的用户上参数化API变得更加容易。
Django REST框架API密钥
这个Django REST框架API密钥包提供了将API密钥授权添加到API中的权限类、模型和助手。它可以用于授权内部或第三方后端和服务(如机器)没有用户帐户。API密钥使用Django的密码散列基础结构安全地存储,可以在Django管理中随时查看、编辑和撤销它们。
Django REST框架角色过滤器
这个Django REST框架角色过滤器包提供了对多个角色类型的简单筛选。