drf(三)—权限控制 问题引出:有些功能(数据)是需要具备一定权限的的用户才能进行访问,例如:VIP才有查看某些数据的功能。 上节内容的补充: def _authenticate(self): for authenticator
问题引出:有些功能(数据)是需要具备一定权限的的用户才能进行访问,例如:VIP才有查看某些数据的功能。
上节内容的补充:
-
def _authenticate(self): for authenticator in self.authenticators: #循环配置文件中的列表认证 try: user_auth_tuple = authenticator.authenticate(self) except exceptions.APIException: self._not_authenticated() raise # 抛出错误 if user_auth_tuple is not None: self._authenticator = authenticator self.user, self.auth = user_auth_tuple return # 函数终止,对象啊中封装元组 # 本次循环无返回。
说明:上述情况的三种返回值
# 1、无返回值 None 表示本次循环中认证组件不产生任何作用,会进行到下一个循环,表示配置文件中列表可以有多个认证对象 # 2、抛出异常 raise "认证失败" # 3.函数终止,对象啊中封装元组 两个值 self.user,self.auth
-
与认证类似,权限与认证流程相似,因为请求都要经过
dispatch
def dispatch(self, request, *args, **kwargs): self.args = args self.kwargs = kwargs request = self.initialize_request(request, *args, **kwargs) self.request = request self.headers = self.default_response_headers # deprecate? try: self.initial(request, *args, **kwargs) #进入功能 if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc: response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs) return self.response
-
initial()函数
def initial(self, request, *args, **kwargs): self.format_kwarg = self.get_format_suffix(**kwargs) neg = self.perform_content_negotiation(request) request.accepted_renderer, request.accepted_media_type = neg version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme self.perform_authentication(request) #认证功能 self.check_permissions(request) # 权限控制功能 self.check_throttles(request)
-
check_permissions()函数
def check_permissions(self, request): for permission in self.get_permissions():# 循环该对象 if not permission.has_permission(request, self): # 不存在验证方法直接进入到下一个类的验证。 # 表示定义的权限类中应该具备一个方法 has_permission() self.permission_denied( request, message=getattr(permission, 'message', None), code=getattr(permission, 'code', None) # 本类不存在使用反射进行获取,两个变量 )
-
get_permissions()函数
def get_permissions(self): # 返回列表生成式,循环生成并存储对象。 return [permission() for permission in self.permission_classes]
-
permission_denied()函数
def permission_denied(self, request, message=None, code=None): if request.authenticators and not request.successful_authenticator: # 如果未认证,或认证失败则抛异常 raise exceptions.NotAuthenticated() raise exceptions.PermissionDenied(detail=message, code=code)
-
PermissionDenied类
class PermissionDenied(APIException): status_code = status.HTTP_403_FORBIDDEN default_detail = _('You do not have permission to perform this action.') default_code = 'permission_denied' # 可以实现定制报错消息。
class SimplePermission(object):
def has_permission(self,request,*args,**kwargs):
# 返回 True 可以访问
#if request.user.user_type != 3:
# return False # 返回False无权访问;
return False
定义视图
class OrderView(APIView):
permission_classes=[SimplePermission,]# 局部使用权限控制器
def get(self,*args,**kwargs):
return JsonResponse(ORDER_DICT)
class SimplePermission(object):
message="您没有权限访问!"# 定义返回没有权限的信息
def has_permission(self,request,*args,**kwargs):
# 返回 True 可以访问
# if request.user.user_type != 3:
# return False # 返回False无权访问;
return False
3.内置权限及全局使用
# BasePermission源码,
class BasePermission(metaclass=BasePermissionMetaclass):
"""
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
我们自定义的权限类中一般需要自定义类中继承该类。
使用:
class MyPermission(BasePermission):
# 继承BasePermission
message="您没有权限访问!!!"
def has_permission(self, request, view):
if request.user.user_type!=3:
return False
return True
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":['app01.utils.auth.MyAuthentication',],
"UNAUTHENTICATED_USER":None, # 匿名,request.user = None
"UNAUTHENTICATED_TOKEN":None,
# 权限配置
"DEFAULT_PERMISSION_CLASSES":['app01.utils.permission.MyPermission',],
}
注意:当配置了全局的权限控制函数后需要在登录窗口中设置权限,permission_classes = []
使用SVIP用户进行查看
普通用户进行查看
继续努力,终成大器!!