「Django REST Framework 框架」Permissions权限解析及应用举例

全部 Django Web 开发文章索引目录传送门:

【Django Web 开发】全部文章目录索引

文章目录
内容介绍
Permissions权限
应用举例
内容介绍
代码内容基于「Django REST Framework API框架」源码版本 3.12.x ,更新内容会进行标记说明对应版本。

身份认证和权限组合使用,用来确定请求是否返回数据还是拒绝请求数据。

Permissions权限
1.确定权限

# 在运行视图前检查每个请求的权限
# 如果检查失败则会引发 exceptions.PermissionDenied 异常并且不会运行视图代码
# 根据以下规则
# 401:请求未成功进行身份验证
# 403:请求已成功通过身份验证,,但权限被拒绝禁止的响应

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

1
2
3
4
5
6
7
8
9
10
11
2.设置权限策略

# 在 Django 项目中的 settings.py 中, 你可以使用全局设置权限访问策略
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',            # IsAuthenticated 仅通过认证的用户
        'rest_framework.permissions.AllowAny',                   # AllowAny 允许所有用户
        'rest_framework.permissions.IsAdminUser',                # IsAdminUser 仅管理员用户
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',  # IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取

    ]
}


# 单个 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) 


# 使用装饰器的方式进行访问策略装饰
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 按位运算符来组合权限

# IsAuthenticatedOrReadOnly
from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
from rest_framework.views import APIView

class ReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS

class ExampleView(APIView):
    permission_classes = [IsAuthenticated|ReadOnly]

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
3.认证的基础方式

# 1. IsAuthenticated
# 允许已认证并通过认证的用户情况可以进行后续操作。

# 2. IsAdminUser
# 用户身份中 user.is_staff 是 True 被允许。

# 3. IsAuthenticatedOrReadOnly
# 允许已认证用户读取和修改,未认证用户只读。
1
2
3
4
5
6
7
8
4.DjangoModelPermissions

# 该权限类与 Django 的标准 django.contrib.auth 模型权限相关联
# 此权限只能应用于 .queryset 属性的视图
# 仅当用户通过身份验证并分配了相关的模型权限时,才会授权。
# POST 请求需要用户对 add 模型具有权限
# PUT、PATCH 请求要求用户对 change 模型具有权限
# DELETE 请求需要用户对 delete 模型具有权限

# 可以覆盖默认行为以支持自定义模型权限
# 例如想要包括 GET 请求的view模型权限
# 要使用自定义模型权限,覆盖 DjangoModelPermissions 并设置 .perms_map 属性
# 如果将此权限与重写 get_queryset() 方法的视图一起使用该视图上可能没有 queryset 属性
# 在这种情况下建议使用 sentinel queryset 标记视图,以便此类可以确定所需的权限
queryset = User.objects.none()  # Django模型权限要求
1
2
3
4
5
6
7
8
9
10
11
12
13
5.DjangoModelPermissionsOrAnonReadOnly

# 与 DjangoModelPermissions 相似
# 允许未经身份验证的用户对 API 进行只读访问
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
      'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}
1
2
3
4
5
6
7
6.DjangoObjectPermissions

# 该权限类与 Django 的标准对象权限框架相关联,允许对模型进行按对象划分的权限
# 使用此权限类需要添加一个支持对象级权限的权限后端django-guardian

# 安装
pip install django-guardian

# settings.py
INSTALLED_APPS = [
    ......
    'guardian',
]

AUTHENTICATION_BACKENDS = (
    # 然后将guardian作为额外的授权BACKEND添加进配置
    'django.contrib.auth.backends.ModelBackend',
    'guardian.backends.ObjectPermissionBackend',
)

# 与 DjangoModelPermissions 一样
# 此权限必须仅应用于具有.queryset 属性或 .get_queryset() 方法的视图
# 当用户通过身份验证并分配了相关的每个对象权限和相关的模型权限后才会授予授权。
# POST 请求要求用户对 add 模型实例具有权限
# PUT、PATCH 请求要求用户对 change 模型实例具有权限
# DELETE 请求要求用户对 delete 模型实例具有权限

# DjangoObjectPermissions 不需要 django-guardian 并且应该同样支持其他对象级后端。与 DjangoModelPermissions 一样,可以覆盖 
# DjangoObjectPermissions 和设置 .perms_map 属性来使用自定义模型权限
# 需要 GET、HEAD 和 OPTIONS 请求的对象级视图权限
# 并且正在将 django-guardian 用作对象级权限后端
# 则需要考虑使用 djangorestframework-guardian 包提供的DjangoObjectPermissionsFilter 类确保列表端点只返回结果
# 包括用户具有适当查看权限的对象

# shell 命令执行
python manage.py migrate
# 生成表单guardian_groupobjectpermission和guardian_userobjectpermission
# 记录了用户/组与model以及model内的具体object的权限对应关系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
7.自定义权限

# 要实现自定义权限重写 BasePermission 
# .has_permission(self, request, view)
# .has_object_permission(self, request, view, obj)
# 方法应返回 True 应授予请求访问权限, 否则则返回 False。
# 测试中请求是读操作或写操作, 你应该检查对常量的请求方法 SAFE_METHODS
# 这是一个包含 'GET'、'OPTIONS' 和 'HEAD' 的一个元组。

# 只有在视图中 has_permission 检查已通过时才会调用实例级别 has_object_permission 方法
# 视图代码应该显式调用 .check_object_permissions(request,obj)
# 如果是通用视图,则默认情况下会为处理此问题(基于函数的视图将需要显式检查对象权限,在失败时引发 PermissionDenied)
# 测试失败则自定义权限将引发 PermissionDenied 异常
# 要更改与异常关联的错误消息
# 直接在自定义权限上实现 message 属性,否则将使用 PermissionDenied 的 default_detail 属性
# 同样要更改与异常关联的代码标识符,直接在您的自定义权限上实现 code 属性
# 否则将使用 PermissionDenied 的  default_codefrom 属性。
if request.method in permissions.SAFE_METHODS:
    # 检查只读请求的权限
else:
    # 检查写请求的权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
应用举例
# 权限类对照阻止列表检查传入请求的 IP 地址, 并在IP被阻止时拒绝该请求。
from rest_framework import permissions

class BlocklistPermission(permissions.BasePermission):
    """
    全局权限检查被阻止的ip。
    """

    def has_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        blocked = Blocklist.objects.filter(ip_addr=ip_addr).exists()
        return not blocked


# 除了针对所有传入请求运行的全局权限外
# 还可以创建仅针对影响特定对象实例的操作运行的对象级别权限
# 通用视图将检查适当的对象级别权限
# 但是如果您要编写自己的自定义视图则需要确保自己检查对象级别权限
# 通过在拥有对象实例后从视图中进行调用 self.check_object_permissions(request, obj) 来实现
# 如果任何对象级权限检查失败则调用将引发 APIException,否则将简单地返回
class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    对象级权限,只允许对象的所有者对其进行编辑。
    假设模型实例具有“所有者”属性。
    """

    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


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值