流程
执行initial()方法
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs)
# Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
# Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# Ensure that the incoming request is permitted
# 身份认证
self.perform_authentication(request)
# 检查权限
self.check_permissions(request)
# 流量限速
self.check_throttles(request)
执行check_permissions()方法
def check_permissions(self, request):
"""
Check if the request should be permitted.
Raises an appropriate exception if the request is not permitted.
"""
# 1.循环对象get_permissions方法的结果,如果自己没有,则去父类寻找
for permission in self.get_permissions():
# 2.判断每个对象中的has_permission方法返回值(其实就是权限判断),这就是为什么我们需要对权限类定义has_permission方法
if not permission.has_permission(request, self):
# 3. 返回无权限信息,也就是我们定义的message共有属性
self.permission_denied(
request, message=getattr(permission, 'message', None)
)
去循环遍历self.get_permissions方法的结果。
get_permissions()方法
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
return [permission() for permission in self.permission_classes]
这里将类权限类实例化和认证一样,循环遍历获得每个认证类的实例,
返回实例列表生成式,如果在视图类中没有的写的话,就会去默认的setting配置中找
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
在check_permissions看到
if not permission.has_permission(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
)
如果实例permission的has_permission方法为空,就执行permission_denied方法
self.permission_denied()
def permission_denied(self, request, message=None):
"""
If request is not permitted, determine what kind of exception to raise.
"""
# 如果不允许请求,请确定引发哪种异常。
if request.authenticators and not request.successful_authenticator:
raise exceptions.NotAuthenticated()
# 如果定义了message属性,则抛出属性值
raise exceptions.PermissionDenied(detail=message)
这里意思是请求不允许就抛异常,到这里其实就结束了
如果有这个权限认证就过,没有就抛出异常
内置权限验证类
rest_framework.permissions
##基本权限验证
class BasePermission(object)
##允许所有
class AllowAny(BasePermission)
##基于django的认证权限,官方示例
class IsAuthenticated(BasePermission):
##基于django admin权限控制
class IsAdminUser(BasePermission)
##也是基于django admin
class IsAuthenticatedOrReadOnly(BasePermission)
- 自定义权限流程
- 继承BasePermission类(推荐)
- 重写has_permission方法
- has_permission方法返回True表示有权访问,False无权访问
.....等等
基本的权限类供我们一些基础需求,但是我们更多的是需要自己单独写权限。
下面我们看下使用方法,基本的单独写权限
使用方法
内部类使用
##单一视图使用,为空代表不做权限验证
class MenuViewSet(ModelViewSet, TreeAPIView):
permission_classes = [MyPremission,]
全局使用
REST_FRAMEWORK = {
#权限
"DEFAULT_PERMISSION_CLASSES":['API.utils.permission.MyPremission'],
}
优先级
单一视图(内部类) > 全局配置(全局)