Django Rest framework Permissions

权限(Permissions)和认证(Authentication)以及节流(Throttling)一起决定一个请求是否会被接受或拒绝。
权限检查会在视图最开始执行,先于视图中的其他代码。权限校验通常使用认证阶段产生的request.userrequest.auth参数。
最简单的权限校验是接受所有携带了认证用户的请求以及用户未被认证的访问只读信息的请求。这中权限控制可以通过REST Framework的IsAuthenticatedOrReadOnly

权限的确定

Rest framework中的权限由permissions列表决定。
在运行视图主体之前,权限列表中的每一权限都会被检查。如果任一权限不满足,则会导致exceptions.PermissionDeniedexceptions.NotAuthenticated
当权限校验失败,则会导致’403 Forbidden’或’401 Unauthorized’相应,遵循以下规则:

  • 请求被成功认证,但权限校验失败,返回403
  • 请求成功认证,最优先认证类没有使用WWW-Authenticate请求头,返回403
  • 请求没有成功认证,最优先认证类使用WWW-Authenticated请求头,返回401并携带WWW-Authenticate响应头。
对象级别的权限

RF权限也支持对象级别的权限校验。对象级别的权限用于校验用户是否允许对特定的对象执行相关操作,对象通常是模型实例。
对象级别的权限在RF的通用视图的get_object()方法被调用时执行。与视图级别的权限相同,当用户没有操作给定对象的权限时,会导致exceptions.PermissionDenied异常。
如果你在自定义视图并希望执行对象级别的权限校验,或者你在一个通用视图中重写了get_object方法,那么你需要在检索特定对象时专门调用.check_object_permissions(request, obj)方法。
要么法奥之PermissionDeniedNoeAuthenticated异常,要么返回响应。
例:

def get_object(self):
    obj = get_object_or_404(self.get_queryset(), pk=self.kwargs["pk"])
    self.check_object_permissions(self.reques, obj)
    return obj

注意 除了DjangoObjectPermissionsrest_framework.permissions并没有实现检查对象操作权限的方法。
如果你希望使用提供的权限类检查对象权限,你必须继承他们并实现Custom permission部分描述的has_object_permission()方法。

对象级别权限的限制

出于对性能的考虑,当响应返回对象列表时,通用视图并不会对queryset中的每一个实例作权限校验。
大部分情况下,当你使用对象级别的权限校验时,你需要设置适当的条件查询queryset,以保证用户见到的都是有操作权限的对象。

设置权限策略

默认的权限策略可以作为全局设置,在settings中设置DEFAULT_PREMISSION_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 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中的全局默认权限。
如果权限继承自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)

注意权限组合支持 &(and),|(or),~(not)

接口参考

AllowAny

这是一种非严格的权限,对请求是否认证不做限制。引用这一权限和不引用权限是一致的,常用于在把某些视图排除校验。

IsAuthenticated

这一权限会拒绝所有非认证请求。

IsAdminUser

这一权限会让视图仅接受user.is_staff为True的请求。

IsAuthenticatedOrReadOnly

这一权限会让视图接受所有有认证用户的请求,或接受没有认证用户但请求方法为GETHEADOPTIONS的请求。

DjangoModelPermissions

这一权限与标准的django.contrib.auth模型权限绑定。只有设置了.queryset属性的视图才会执行此类权限校验。只有用户被认证且具有相关权限的请求才会被接受。

  • POST请求需要用户具有add权限
  • PUT/PATCH请求需要用户具有change权限
  • DELETE请求需要用户具有delete权限
没有queryset属性的视图使用此权限

如果视图中重写了get_queryset()方法,那么可能没有定义queryset属性。这种情况下,建议在视图中标记一个虚拟的query_set属性,这样可以执行需要的权限校验。比如:
queryset = User.objects.none() # Required for DjangoModelPermissions

DjangoModelPermissionsOrAnonReadOnly

在DjangoModelPermission的基础上允许未认证用户访问只读接口

DjangoObjectPermissions

这一权限与django标注的对象权限框架绑定,这些框架可以校验对象级别的权限,你需要添加支持对象级别权限的后台才能使用这一权限类,比如django-guardian
和DjangoModelPermissions一样,这一权限同样只适用于定义了.queryset属性或.get_queryset()方法的视图。只用用户被认证且具有指定对象的相关权限时请求才会被接受。
注意如果你希望GETHEAD以及OPTIONS请求也校验对象界别的权限且djangp-guardian作为对象级别权限的后台,那么可以考虑使用djangorestframework-guardianDjangoObjectPermissionsFilter类。他可以保证list接口返回的对象只包含用户有相应权限的对象。

自定义权限

继承BasePermission并调用以下方法即可使用自定义的权限:

  • .has_permission(self, request, view)
  • .has_object_permission(self, request, view, obj)
    这些方法在请求可以被接受时返回True否则返回False。
    如果要检查一个请求是读操作还是写操作,只要将请求方法与常量SAFE_METHODS对比即可,该常量是包含GETOPTIONS以及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)才会执行实例级别的权限校验。如果你使用通用视图,那么已经默认调用了该方法。
如果校验失败,自定义的权限必须抛出PermissionDenied异常。通过定义message参数可以修改与异常关联的错误信息,否则会使用PermissionDenieddefault_detail属性。

from rest_framework import permissions

class CustomerAccessPermission(permissions.BasePermission):
    message = 'Adding customers not allowed.'

    def has_permission(self, request, view):
    ...

以下是一个检查请求的IP地址是否在黑名单中的权限类:

from rest_framework import permissions

class 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异常。
同时,通用视图只会对检索但个模型实例的视图校验对象级别的权限,如果你需要对列表视图作对象级别的筛选,那么你需要筛选和时查询集。见筛选文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django REST framework是一个基于Django的强大Web API框架,可以帮助开发者快速构建RESTful API。下面是Django REST framework后端开发的文档。 ## 安装 可以通过pip安装Django REST framework: ``` pip install djangorestframework ``` ## 配置 1. 将`rest_framework`添加到`INSTALLED_APPS`中: ```python INSTALLED_APPS = [ ... 'rest_framework', ... ] ``` 2. 添加REST framework的默认设置到`settings.py`文件中: ```python REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', ], 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ], } ``` ## 序列化 Django REST framework的核心是序列化。它允许将复杂的Python数据结构转换为JSON、XML等格式。 ### 创建序列化器 1. 创建一个`serializers.py`文件,并导入`serializers`: ```python from rest_framework import serializers from .models import Book ``` 2. 创建一个`BookSerializer`类: ```python class BookSerializer(serializers.ModelSerializer): class Meta: model = Book fields = '__all__' ``` `fields`属性指定了需要序列化的模型字段。 ### 使用序列化器 在视图中使用序列化器,可以将模型转换为JSON格式的响应。 ```python from rest_framework import generics from .models import Book from .serializers import BookSerializer class BookList(generics.ListCreateAPIView): queryset = Book.objects.all() serializer_class = BookSerializer ``` ## 视图 Django REST framework提供了多种视图,包括基于函数的视图和基于类的视图。 ### 基于函数的视图 1. 创建一个`views.py`文件,并导入Django REST framework的视图: ```python from rest_framework.decorators import api_view from rest_framework.response import Response ``` 2. 创建一个`book_list`函数: ```python @api_view(['GET', 'POST']) def book_list(request): if request.method == 'GET': books = Book.objects.all() serializer = BookSerializer(books, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = BookSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=201) return Response(serializer.errors, status=400) ``` `@api_view`装饰器表示该视图只接受`GET`和`POST`请求。`BookSerializer`用于将模型转换为JSON格式的响应。 ### 基于类的视图 1. 创建一个`views.py`文件,并导入Django REST framework的视图: ```python from rest_framework import generics ``` 2. 创建一个`BookList`类: ```python class BookList(generics.ListCreateAPIView): queryset = Book.objects.all() serializer_class = BookSerializer ``` `queryset`属性指定需要序列化的模型,`serializer_class`属性指定使用的序列化器。 ## 路由 Django REST framework的路由是基于Django的URLconf的。可以使用Django REST framework自带的`DefaultRouter`或者自定义路由。 ### 使用`DefaultRouter` 1. 创建一个`urls.py`文件,并导入`DefaultRouter`: ```python from rest_framework.routers import DefaultRouter ``` 2. 在`views.py`中导入视图,并创建一个`router`: ```python from .views import BookList router = DefaultRouter() router.register(r'books', BookList) ``` `r'books'`是路由名称,`BookList`是视图类。 3. 在`urls.py`中将路由添加到URLconf中: ```python from django.urls import path, include urlpatterns = [ path('', include(router.urls)), ] ``` ### 自定义路由 1. 创建一个`urls.py`文件,并导入视图: ```python from django.urls import path from .views import book_list ``` 2. 创建一个URLconf: ```python urlpatterns = [ path('books/', book_list, name='book-list'), ] ``` `book_list`是一个基于函数的视图。 3. 在主URLconf中包含自定义路由: ```python from django.urls import path, include urlpatterns = [ path('', include('myapp.urls')), ] ``` ## 认证和权限 Django REST framework提供了多种认证和权限选项,可以通过`settings.py`中的`DEFAULT_AUTHENTICATION_CLASSES`和`DEFAULT_PERMISSION_CLASSES`设置默认选项。 ### 认证 Django REST framework提供了多种认证选项,包括SessionAuthentication、BasicAuthentication和TokenAuthentication等。 ```python REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.TokenAuthentication', ], } ``` ### 权限 Django REST framework提供了多种权限选项,包括AllowAny、IsAuthenticated和IsAdminUser等。 ```python REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', 'rest_framework.permissions.IsAuthenticated', 'rest_framework.permissions.IsAdminUser', ], } ``` ## 参考资料 - [Django REST framework官方文档](https://www.django-rest-framework.org/) - [Django REST framework教程](https://www.django-rest-framework.org/tutorial/1-serialization/)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值