与 authentication 和 throttling 一起,permission 决定是应该接受还是拒绝访问请求。
权限检查总是在视图的最开始处运行,在任何其他代码被允许进行之前。权限检查通常会使用 request.user 和 request.auth 属性中的认证信息来确定是否允许传入请求。
权限用于授予或拒绝不同类别的用户访问 API 的不同部分。
最简单的权限是允许通过身份验证的用户访问,并拒绝未经身份验证的用户访问。这对应于 REST framework 中的 IsAuthenticated 类。
稍微宽松的权限会允许通过身份验证的用户完全访问,而未通过身份验证的用户只能进行只读访问。这对应于 REST framework 中的 IsAuthenticatedOrReadOnly 类。
设置权限策略
默认权限策略可以使用 DEFAULT_PERMISSION_CLASSES setting 全局设置。例如
REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
如果未指定,则此设置默认为允许无限制访问:
'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.AllowAny', )
当然也可以基于 APIView 类的视图上设置身份验证策略
查看源码,restframework现成的类有7个,介绍如下常用四个
AllowAny:允许无限制访问
IsAuthenticated :允许访问任何经过身份验证的用户,并拒绝访问任何未经身份验证的用户
IsAdminUser:允许超级用户访问
IsAuthenticatedOrReadOnly:对经过身份验证的用户的允许完全访问,但对未经身份验证的用户的允许只读访问
@six.add_metaclass(BasePermissionMetaclass) class BasePermission(object): """ A base class from which all permission classes should inherit. """ def has_permission(self, request, view): """ Return `True` if permission is granted, `False` otherwise. """ return True def has_object_permission(self, request, view, obj): """ Return `True` if permission is granted, `False` otherwise. """ return True
但完全可以我们自己来写,仅需要面向上述源码任意一个接口即可。
apps/app/permissions.py
from rest_framework.permissions import BasePermission class IsLoginReadOnly(BasePermission): """ 自定义权限设置 """ def has_permission(self,request,view): return all((request.user.is_authenticated,request.user.is_staff))
如果你需要测试请求是读取操作还是写入操作,则应该根据常量SAFE_METHODS
检查请求方法,SAFE_METHODS
是包含'GET'
, 'OPTIONS'
和'HEAD'
的元组
if request.method in permissions.SAFE_METHODS: # 检查只读请求的权限 else: # 检查读取请求的权限
views.py
from rest_framework import mixins from rest_framework import viewsets from .models import UserProfile from .serializers import UserProfileSerializer from .permissions import IsAuthenticatedOrReadOnly class UsersListViewSets(viewsets.GenericViewSet,mixins.ListModelMixin): """ 用户列表 """ queryset = UserProfile.objects.all() serializer_class = UserProfileSerializer permission_classes = (IsAuthenticatedOrReadOnly,)
对象级权限
实际场景下,我们往往需要对权限细分:
POST 请求要求用户对模型实例具有 add 权限。
PUT 和 PATCH 请求要求用户对模型实例具有 edit 权限。
DELETE 请求要求用户对模型实例具有 delete 权限。
这就需要我们重写APIView下的has_permissions方法
views.py
from .permission import UserAddPermission from .permission import UserDeletePermission from .permission import UserEditPermission from .permission import UserQueryPermission # permission_classes = (UserQueryPermission,) def get_permissions(self): if self.action == "create": self.permission_classes = (UserAddPermission,) elif self.action == "list": self.permission_classes = (UserQueryPermission,) elif self.action == "update": self.permission_classes = (UserEditPermission,) elif self.action == "destroy": self.permission_classes = (UserDeletePermission,) return super().get_permissions()
permission.py
class UserAddPermission(BasePermission): """ 增加用户权限 """ def has_permission(self, request ,view): user = request.user if user.is_authenticated: permissons = user.has_permissons() return "add user" in permissons
遇到了问题,即使UsersListViewSets继承了viewsets.ModelViewSet,该接口依旧只允许GET, POST, HEAD, OPTIONS四种方法,
没有put和delete.
解决:自己手动绑定。。。
def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) def delete(self,request, *args, **kwargs): return self.destroy(request, *args, **kwargs)