Django-restframework22 Permissions

身份验证或标识本身通常不足以获得访问信息或代码的权限。为此,请求访问的实体必须具有授权。

1 简介

permissions和authentication,throttling一起,确定一个请求是否具有访问权限。
权限检查一般在请求执行到的动作之前进行检查。Permission 一般会使用用户的认证信息(request.user和request.auth)来确定接收到的请求是否应该被允许。
Permissions被用来授予不同种类的用给在不同的接口的访问权限。
简单的形式就是授予认证用户全部权限,拒绝未认证的用户访问请求。这与IsAuthenticated权限类一致。
不那么严格的方式就是未认证用户具有只读权限(IsAuthenticatedOrReadOnly)。

1 确定认证权限

权限一般被定义成一系列权力类的列表(permission_classes)。
在运行主体之前,会先检查列表中的每一个权限,如果全都失败,产生一个exceptions.PermissionDenied或者exceptions.NotAuthenticated,主体部分将不会运行。
如果权限检查根据以下2规则返回”403 Forbidden”或”401 Unauthorized” :
- 认证成功,但是权限不够,403 Forbidden response
- 认证失败,优先级最高的认证类没有使用WWW-Authenticate响应头,将会返回HTTP 403 Forbidden response
- 认证失败,优先级最高的认证类使用了WWW-Authenticate响应头,将返回HTTP 401 Unauthorized response

2 对象级权限(Object level permissions)

对象级权限用于为确定用户是否有权对对象执行操作,该对象一般指模型实例
对象级权限一般在.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())
    self.check_object_permissions(self.request, obj)
    return obj

对象级权限的局限性
出于性能的原因,当返回一个对象列表时,通用视图不会自动将对象级权限应用到queryset中的每个实例。
通常,当您使用对象级权限时,您还需要适当地过滤queryset,以确保用户只对允许查看的实例具有可见性。

3 设置权限

默认的全局设置为:DEFAULT_PERMISSION_CLASSES

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}

如果没有指定,设置为任何人均可以为访问

'DEFAULT_PERMISSION_CLASSES': (
   'rest_framework.permissions.AllowAny',
)

也可以在视图函数或者视图类中设置权限类

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)

2. 接口指南

  1. AllowAny:允许任何人访问,和权限设置为空一样
  2. IsAuthenticated:允许认证成功
  3. IsAdminUser:只允许(user.is_staff=True)的用户访问
  4. IsAuthenticatedOrReadOnly:认证用户全部权限,未认证用户只读
  5. DjangoModelPermissions

关系到 django.contrib.auth model permissions. 这个权限只能应用在拥有queryset属性的视图中。
只有对用户进行了身份验证,并分配了相关的模型权限,才会授予授权。
- POST要求用户有add权限
- PUT和PATCH要求用户有change权限
- DELETE要求用户有delete权限
支持自定义模型权限,默认行为可以被重写,例如可以为GET请求设置权限。
自定义模型权限(DjangoModelPermissions)时,需要重写然后设置.perms_map属性
在没有设置queryset属性的视图中使用模型权限
如果您使用的是重写了get_queryset()方法的视图,那么视图中可能没有.queryset属性.建议也写上一个queryset对视图进行标记,这样该类就可以确定所需的权限。例如:

queryset = User.objects.none()
  1. DjangoModelPermissionsOrAnonReadOnly :未认证用户具有只读权限
  2. DjangoObjectPermissions:对象级权限
    关系到django的 object permissions framework,其允许模型中的每个对象具有权限。为了使用此类,你还需要一个支持对象级权限的额权限许可后端,比如django-guardian。具体使用和 DjangoModelPermissions 类似。视图必须具有queryset属性或者get_queryset()方法。
    如果想支持GET, HEAD和OPTIONS请求,需要添加DjangoObjectPermissionsFilter类来确保返回结果中包含的对象是用户有权操作的。

3. 自定义权限

首先继承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)方法。如果你使用generic views的话就会默认帮你处理。
自定义权限类如果检查失败,会抛出PermissionDenied异常。可以自定义message属性,用来表示详情。否则的话,默认使用default_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

4 三方包

  1. Composed Permissions:提供复杂而且具有多层的对象权限管理
  2. REST Condition:使用逻辑判断结合权限认证
  3. DRY Rest Permissions:DRY Rest权限包提供默认和自定义操作定义不同权限的能力。这个包是为具有权限的应用(app)设计的,这些应用程序是根据应用程序的model中定义的关系而生成的。它还支持通过API的序列化器返回到客户端应用程序的权限检查。此外,它还支持向默认值和自定义列表操作添加权限,以限制每个用户检索的数据。
  4. Django Rest Framework Roles:为API接口配置多种类型的user
  5. Django Rest Framework API Key:允许您确保向服务器发出的每个请求都需要一个API密钥头。您可以从django管理界面生成一个。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Django-rest-framework是一个用于构建Web API的强大框架,它提供了许多有用的工具和库,可以帮助我们轻松地构建出一个安全可靠的用户注册和登录系统。 下面是一个简单的Django-rest-framework用户注册与登录的实现: 首先,我们需要安装Django-rest-framework: ``` pip install djangorestframework ``` 接着,我们需要在settings.py文件中添加以下配置: ```python INSTALLED_APPS = [ # ... 'rest_framework', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], } ``` 上面的配置将启用TokenAuthentication身份验证和IsAuthenticated权限,这将确保只有已登录的用户才能访问我们的API。 现在,我们可以创建一个名为"users"的Django应用程序,并定义以下模型: ```python from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): pass ``` 接着,我们需要定义序列化器来将User模型转换为JSON格式: ```python from rest_framework import serializers from .models import User class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('username', 'email', 'password') extra_kwargs = {'password': {'write_only': True}} def create(self, validated_data): user = User.objects.create_user( username=validated_data['username'], email=validated_data['email'], password=validated_data['password'] ) return user ``` 上面的代码定义了一个UserSerializer序列化器,将User模型转换为JSON格式。我们使用Meta类来指定模型和要序列化的字段,以及一些额外的参数。在create方法中,我们使用create_user方法创建新用户。 现在,我们可以定义视图来处理用户注册和登录请求: ```python from rest_framework import generics, permissions, status from rest_framework.response import Response from rest_framework.authtoken.models import Token from rest_framework.views import APIView from django.contrib.auth import authenticate, login from .models import User from .serializers import UserSerializer class RegisterView(generics.CreateAPIView): queryset = User.objects.all() serializer_class = UserSerializer permission_classes = [permissions.AllowAny] def post(self, request): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) class LoginView(APIView): permission_classes = [permissions.AllowAny] def post(self, request): username = request.data.get('username') password = request.data.get('password') user = authenticate(request, username=username, password=password) if user is not None: login(request, user) token, created = Token.objects.get_or_create(user=user) return Response({'token': token.key}) else: return Response({'error': 'Invalid credentials'}) ``` 上面的代码定义了RegisterView和LoginView视图。RegisterView视图处理用户注册请求,LoginView视图处理用户登录请求。我们在视图中使用UserSerializer序列化器来验证输入数据,并使用TokenAuthentication身份验证来保护API。 现在我们已经完成了用户注册和登录的实现。可以使用POST请求来测试我们的API: - 用户注册: ``` POST /api/register/ { "username": "testuser", "email": "testuser@example.com", "password": "testpassword" } ``` - 用户登录: ``` POST /api/login/ { "username": "testuser", "password": "testpassword" } ``` 如果登录成功,API将返回一个含Token身份验证密钥的JSON响应。现在,我们可以将此密钥用于所有受保护的API请求中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆豆orz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值