DRF_权限和认证

DRF权限认证

1. 认证Authentication

1.1 全局认证

全局认证只需要在Django的配置文件中加入一个字典即可,如下:

# project/settings.py

REST_FRAMEWORK = {
    # DRF中认证的配置
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',		# 基本认证
        'rest_framework.authentication.SessionAuthentication',		# session认证
    ]
}

1.2 局部认证

局部认证需要在视图中配置,通过在每个视图中通过设置authentication_classess属性来设置局部认证

# project/app/views.py

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView, CreateAPIView, UpdateAPIView, ListAPIView, RetrieveAPIView, DestroyAPIView
from rest_framework.response import Response
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
from rest_framework.viewsets import ModelViewSet

from .models import BookMessage
from rest_framework import status
from .serializer import BookSerializer
from rest_framework.decorators import action
from rest_framework.authentication import SessionAuthentication

# Create your views here.

class BookOperation(ModelViewSet):
	queryset = BookMessage.objects.all()
	serializer_class = BookSerializer
	# 认证
	authentication_classes = [SessionAuthentication]

当全局认证及局部认证同时存在时,优先局部认证。

认证失败可能有两种可能的返回值:

  • 401-------------Unauthorized 未认证
  • 403-------------Permission Denied 权限被禁止

2. 权限 Permission

全局权限及局部权限设置方法和认证类似。

2.1 全局权限

  • IsAuthenticated----------------------允许普通用户访问
  • AllowAny--------------------------------允许任何用户访问
  • IsAdminUser----------------------------允许超级管理员访问
  • IsAuthenticatedOrReadOnly------- 认证的用户可以完全操作,否则只能get读取

全局配置方法,在配置文件汇总添加:

# project/app/settings.py

REST_FRAMEWORK = {
    # DRF中认证的配置
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',		# 基本认证
        'rest_framework.authentication.SessionAuthentication',		# session认证
    ],
    # DRF中权限的配置:如果没有指明,系统默认的权限是允许所有人访问的
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permission.IsAuthenticated',
        'rest_framework.permission.AllowAny',
        'rest_framework.permission.IsAdminUser'
    ]
}

2.2 局部权限

局部权限需要在视图中配置,通过在每个视图中通过设置permission_classess属性来设置局部权限

# project/app/views.py

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView, CreateAPIView, UpdateAPIView, ListAPIView, RetrieveAPIView, DestroyAPIView
from rest_framework.response import Response
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
from rest_framework.viewsets import ModelViewSet

from .models import BookMessage
from rest_framework import status
from .serializer import BookSerializer
from rest_framework.decorators import action
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import AllowAny,IsAdminUser

# Create your views here.

class BookOperation(ModelViewSet):
	queryset = BookMessage.objects.all()
	serializer_class = BookSerializer
	authentication_classes = [SessionAuthentication]
	# 只允许管理员访问
	permission_classes = [IsAdminUser]

2.3 自定义权限

如需自定义权限,需继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部

  • .has_permission(self, request, view):是否可以访问视图, view表示当前视图对象,如果没有设置的话默认的是True,如果设置,False则表示所有的用户都不能访问该视图
  • .has_object_permission(self, request, view, obj):是否可以访问数据对象, view表示当前视图, obj为数据对象,控制视图能够访问添加了权限控制类的数据对象
# project/app/views.py

# 自定义权限
class MyPermission(BasePermission):
	def has_permission(self, request, view)
		"""让所有用户都有权限"""
		return True
    def has_object_permission(self, request, view, obj):
        """用户是否有权限访问添加了权限控制类的数据对象"""
        # 需求:用户能够访问id为1,3的对象,其他的不能够访问
        if obj.id in (1, 3):
        	return True
        else:
        	return False

class BookInfoViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
    # 表示登录有权限
    permission_classes = [IsAuthenticated]
    # 表示所有用户都有权限,只能够访问id 为1,3的数据
    permission_classes = [MyPermission]

2.4 对视图集查询集单独做权限控制

上述自定义权限只能对接口做整体的权限控制,并不能根据用户角色权限返回相应的查询集,即不同用户返回不同结果。

2.4.1 在filter_backends中添加自定义的过滤类

# project/app/views.py

class ViewSetPermission(BaseFilterBackend):

    def filter_queryset(self, request, queryset, view):
        user_id = request.user.id

        # 添加逻辑判断,对查询集进行过滤
        if request.user.role.permission_name != 1:
            queryset = queryset.filter(sys_user=user_id)

        return queryset


# 模型管理视图
class ModelManageViews(mixins.ListModelMixin, GenericViewSet):
    """
    list:
        查看生成模型列表
    delete:
        删除模型
    """
    queryset = User.objects.all()
    serializer_class = UserSer

    # 权限:自定义权限类
    permission_classes = (MyPermission,)

    # 排序和过滤
    filter_backends = [OrderingFilter, SearchFilter, ViewSetPermission]


2.4.2 对修改和删除的权限控制

增加自定义的过滤类,只能对查询集进行过滤,对删除和修改的接口,虽然也支持,但并没有返回结果,因此还需要改写接口。

# project/app/views.py

class ViewSetPermission(BaseFilterBackend):

    def filter_queryset(self, request, queryset, view):
        user_id = request.user.id

        # 添加逻辑判断,对查询集进行过滤
        if request.method == 'get' and request.user.role.permission_name != 1:
            queryset = queryset.filter(sys_user=user_id)

        return queryset
    
    
class PermissionSet:
    """
    控制权限,返回是否有权限
    """
    # 此方法用于判断请求用户是否有删除权限
    def check_delete_permission(self, request, **kwargs):
        user = request.user
        # 如果是超级用户,则给与删除权限
        if user.role.permission_name == 1:
            return True
        # 临时用户
        elif user.role.permission_name == 3:
            return False


# 模型管理视图
class ModelManageViews(mixins.ListModelMixin,
                       mixins.DestroyModelMixin,
                       GenericViewSet,
                       PermissionSet):
    """
    list:
        查看生成模型列表
    delete:
        删除模型
    """
    queryset = User.objects.all()
    serializer_class = UserSer

    # 权限:自定义权限类
    permission_classes = (MyPermission,)

    # 排序和过滤
    filter_backends = [OrderingFilter, SearchFilter, ViewSetPermission]

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if not self.check_delete_permission(request):
            return Response(data={"message": "暂无权限"}, status=status.HTTP_401_UNAUTHORIZED)

        self.perform_destroy(instance)
        return Response(status=status.HTTP_200_OK)

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Joyce Lee

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

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

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

打赏作者

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

抵扣说明:

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

余额充值