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)