【djangorestframework】10、Permissions(权限)
权限(Permissions)
- 认证或识别本身通常不足以获得对信息或代码的访问。为此,请求访问的实体必须具有授权。--Apple 开发人员文档
- 与身份验证和限流一起,权限确定是否应该授予或拒绝访问请求。
- 在允许任何其他代码继续之前,权限检查始终在视图的最开始运行。权限检查通常会使用request.user和request.auth属性中的认证信息来确定是否允许传入请求。
- 权限用于授予或拒绝不同类型的用户访问API的不同部分。
- 最简单的权限类型是允许访问任何经过身份验证的用户,并拒绝访问任何未经身份验证的用户。这对应于REST framework中的IsAuthenticated类。
- 稍微宽松的权限会允许通过身份验证的用户完全访问,而未经身份验证的用户只能进行只读访问。这对应于REST framework中的IsAuthenticatedOrReadOnly类。
如何确定权限(How permissions are determined)
- REST framework中的权限始终被定义为权限类的列表。
- 在运行视图的主体之前,列表中的每个权限都会被检查。如果任何权限检查失败,则会引发exceptions.PermissionDenied或exceptions.NotAuthenticated异常,并且视图的主体不会再运行。
- 当权限检查失败时,根据以下规则,将返回"403 Forbidden"或"401 Unauthorized"响应:
- 请求成功通过身份验证,但权限被拒绝。--将返回403 Forbiddne响应
- 请求未成功通过身份验证,并且最高优先级身份验证类未使用WWW-Authenticate标头。--将返回403 Forbidden响应
- 请求未成功通过身份验证,并且最高优先级身份验证类使用WWW-Authenticate标头。--将返回HTTP 401 Unauthorized响应,并附带适当的WWW-Authenticate标头
对象级权限(Object level permissions)
- REST framework权限还支持对象级权限。对象级权限用于确定是否允许用户对特定对象进行操作,该特定对象通常是指模型实例。
- 当.get_object()被调用时,对象级权限由REST framework的通用视图运行。与视图级权限一样,如果用户不被允许对给定对象进行操作,则会引发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
对象级权限的限制(Limitations of object level permissions)
- 出于性能原因,在返回对象列表时,通用视图不会自动将对象级权限应用于查询集中的每个实例。
- 通常,当你使用对象级权限时,你还需要适当地过滤查询集,以确保用户只能看到他们被允许查看的实例。
设置权限策略(Setting the permission policy)
- 可以使用DEFAULT_PERMISSION_CLASSES setting全局设置默认权限策略。例如:
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 APIView
class 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)
- 注意:当通过类属性或装饰器设置新的权限类时,你会告诉视图忽略settings.py文件上设置的默认列表。
API参考
AllowAny
- AllowAny权限类将允许不受限制的访问,不管请求是经过身份验证还是未经过身份验证。
- 此权限不是严格要求的,因为你可以通过使用空列表或元祖进行权限设置来获得相同的结果,但你可能会发现指定此类很有用,因为它使意图明确。
IsAuthenticated
- IsAuthenticated权限类将拒绝任何未经身份验证的用户的权限,否则允许权限。
- 如果你希望API仅供注册用户访问,则此权限适用。
IsAdminUser
- IsAdminUser权限类将拒绝任何用户的权限,除非在user.is_staff为True的情况下权限被允许。
- 如果你希望API仅对受信任的管理员子集进行访问,则此权限是合适的。
IsAuthenticatedOrReadOnly
- IsAuthenticatedOrReadOnly将允许经过身份验证的用户执行任何请求。如果请求方法是"安全"的方法之一(GET, HEAD, OPTIONS),则只允许未授权用户的请求。
- 如果你希望API允许匿名用户拥有读取权限,并且只允许对经过身份验证的用户拥有写入权限,则此权限是合适的。
DjangoModelPermissions
- 此权限类与Django的标准django.contrib.auth模型权限绑定。此权限只能应用于具有.queryset属性集的视图。只有在用户经过身份验证并分配了相关模型权限时,才会获得授权。
- POST请求要求用户在模型上具有add权限
- PUT和PATCH请求要求用户在模型上具有change权限
- DELETE请求要求用户在模型上具有delete权限
- 还可以重写默认行为以支持自定义模型权限。例如,你可能想要包含GET请求的view模型权限。
- 要使用自定义模型权限,请重写DjangoModelPermissions并设置.perms_map属性。有关详细信息,请参阅源代码。
使用不包含queryset属性的视图(Using with views that to do not include a queryset attribute)
- 如果你将此权限与重写的get_queryset()方法的视图一起使用,则视图上可能没有queryset属性。在这种情况下,我们建议还用前哨查询集标记视图,以便该类可以确定所需的权限。例如:
queryset = User.objects.none() # Required for DjangoModelPermissions
DjangoModelPermissionsOrAnonReadOnly
- 与DjangoModelPermissions类似,但也允许未经身份验证的用户对API的进行只读访问。
DjangoObjectPermissions
- 该权限类与Django的标准对象权限框架绑定,该框架允许模型上的每个对象权限。要使用此权限类,你还需要添加支持对象级权限的权限后端。例如django-guardian
- 与DjangoModelPermissions一样,此权限只能应用于具有.queryset属性或.get_queryset()方法的视图。只有在用户经过身份验证且分配了相关的每个对象权限和相关的模型权限时,才会获得授权。
- POST请求要求用户在模型实例上具有add权限
- PUT和PATCH请求要求用户在模型实例上具有change权限
- DELETE请求要求用户在模型实例上具有delete权限。
- 请注意,DjangoObjectPermissions不需要django-guardian软件包,并且应同样支持其他对象级后端。
- 与DjangoModelPermissions一样,你可以通过重写DjangoObjectPermissions并设置.perms_map属性来使用自定义模型权限。有关详细信息,请参阅源代码
- 注意:如果你需要GET、HEAD和OPTIONS请求的对象级view权限,则还需要考虑添加DjangoObjectPermissionsFilter类,以确保列表端点只返回包含用户具有适当查看权限的对象的结果。
自定义权限(Custom Permissions)
- 要实现自定义权限,请重写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_permission检查通过时才会调用实例级别的has_object_permission方法。还要注意,为了运行实例级检查,视图代码应显示调用.check_object_permissions(request, obj)。如果你使用的是通用视图,则默认情况下将为你处理.(基于函数的视图需要显式检查对象权限,在失败时引发PermissionDemied。)
- 如果测试失败,自定义权限将引发PermissionDenied异常。要修改与异常相关的错误信息,请直接在自定义权限上实现message属性。否则,将使用PermissionDenied中的default_detail属性
from rest_framework import permissions
class CustomerAccessPermission(permissions.BasePermission):
message = 'Adding customers not allowed.'
def has_permission(self, request, view):
...
- 举个例子:
- 以下是根据黑名单检查传入请求的IP地址的权限类的示例,并且如果IP已被列入黑名单,则拒绝该请求。
from rest_framework import permissions
class BlacklistPermission(permissions.BasePermission):
"""
对列入黑名单的IP进行全局权限检查。
"""
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):
"""
对象级权限,仅允许对象的所有者编辑它。
假设模型实例具有 `owner` 属性。
"""
def has_object_permission(self, request, view, obj):
# 任何请求都允许读取权限,
# 所以我们总是允许 GET,HEAD 或 OPTIONS 请求。
if request.method in permissions.SAFE_METHODS:
return True
# 实例必须具有名为 `owner` 的属性。
return obj.owner == request.user
- 请注意,通用视图将检查适当的对象级权限,但如果你正在编写自己的自定义视图,则需要确保检查自己的对象级权限。你可以通过在拥有对象实例后从视图中调用self.check_object_permissions(request, obj)来完成此操作。如果任何对象级权限检查失败,此调用将引发适当的APIException,否则将简单地返回。
- 还要注意,通用视图仅检查检索单个模型实例的视图的对象级权限。如果需要对列表视图进行对象级别过滤,则需要单独过滤查询集。有关详细信息,请参阅过滤文档。
第三方包(Third party packages)
- 以下是可用的第三方包
Composed Permissions
- Composed Permissions包使用小的和可重用性组件来提供一种定义复杂和多深度(带逻辑运算符)权限对象的简单方法
REST Condition
- REST Condition包是以简单方便的方式构建复杂权限的另一种扩展。该扩展允许你将权限与逻辑运算符组合在一起。
DRY Rest Permissions
- DRY Rest Permissions包提供了为单个默认和自定义操作定义不同权限的能力。此包括用于具有从应用程序数据模型中定义的关系派生的权限的应用程序。它还支持通过API的序列化器将权限检查返回给客户端应用程序。此外,它还支持向默认和自定义列表操作添加权限,以限制每个用户检索的数据。
Django Rest Framework Roles
- Django Rest Frameworl Roles包使你在多种类型的用户上参数化API更轻松
Django Rest Framework API Key
- Django Rest Framework API Key包允许你确保对服务器发出的每个请求都需要API密钥头。你可以从Django管理界面生成一个。
Django Rest Framework Role Filters
- Django Rest Framework Role Filters包提供对多种类型角色的简单过滤。
本文来自博客园,作者:郭祺迦,转载请注明原文链接:https://www.cnblogs.com/guojie-guojie/p/16190687.html