一.请求来到之后,都要先执行dispatch方法
def dispatch(self, request, *args, **kwargs): """ `.dispatch()` is pretty much the same as Django's regular dispatch, but with extra hooks for startup, finalize, and exception handling. """ self.args = args self.kwargs = kwargs 第一步:对request进行加工(添加数据) request = self.initialize_request(request, *args, **kwargs) self.request = request self.headers = self.default_response_headers # deprecate? try: #第二步: #处理版权信息 #认证 #权限 #请求用户进行访问频率的限制 self.initial(request, *args, **kwargs) # Get the appropriate handler method 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 # 第三步、执行:get/post/put/delete函数 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
二.下面我们直接分析第二步
1.self.initial(request,*args,*kwargs)可以看到做了以下操作
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. #2.1 处理版本信息 version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted #2.2 认证 self.perform_authentication(request) # 2.3 权限 self.check_permissions(request) # 2.4 请求用户进行访问频率的限制 self.check_throttles(request)
2.self.check_permissions(request)具体干了什么
def check_permissions(self, request): # 遍历权限对象列表得到一个个权限对象(权限器),进行权限认证 for permission in self.get_permissions(): # 权限类一定有一个has_permission权限方法,用来做权限认证的 # 参数:权限对象self、请求对象request、视图类对象 # 返回值:有权限返回True,无权限返回False if not permission.has_permission(request, self): self.permission_denied( request, message=getattr(permission, 'message', None) )
3.其中循环遍历了self.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]
4.进去后发现了一个熟悉的self.permission_classes 是api_settings中的系统权限类
'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', ],
5.这四个系统权限类,我们他们具体看看做了些什么
""" 1)AllowAny: 认证规则全部返还True:return True 游客与登陆用户都有所有权限 2) IsAuthenticated: 认证规则必须有登陆的合法用户:return bool(request.user and request.user.is_authenticated) 游客没有任何权限,登陆用户才有权限 3) IsAdminUser: 认证规则必须是后台管理用户:return bool(request.user and request.user.is_staff) 游客没有任何权限,登陆用户才有权限 4) IsAuthenticatedOrReadOnly 认证规则必须是只读请求或是合法用户: return bool( request.method in SAFE_METHODS or request.user and request.user.is_authenticated ) 游客只读,合法用户无限制 """
6.分析以上四个系统权限类,他们返回值都是bool值 都是判断各自的想要实现的认证规则,因此我们也可以模仿他们写一个这样的自定义权限类
自定义权限类
全局配置:settings.py
REST_FRAMEWORK = { # 权限类配置 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', ], }
这是全局配置,而且其中是AllowAny 游客和登录用户都有所有权限 因此 我们可以配置局部配置
局部配置 :views.py
# api/views.py from rest_framework.permissions import IsAuthenticated class TestAuthenticatedAPIView(APIView): permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): return APIResponse(0, 'test 登录才能访问的接口 ok')
自定义权限类
""" 1) 创建继承BasePermission的权限类 2) 实现has_permission方法 3) 实现体根据权限规则 确定有无权限 4) 进行全局或局部配置 认证规则 i.满足设置的用户条件,代表有权限,返回True ii.不满足设置的用户条件,代表有权限,返回False """
# utils/permissions.py from rest_framework.permissions import BasePermission from django.contrib.auth.models import Group class MyPermission(BasePermission): def has_permission(self, request, view): # 只读接口判断 r1 = request.method in ('GET', 'HEAD', 'OPTIONS') # group为有权限的分组 group = Group.objects.filter(name='管理员').first() # groups为当前用户所属的所有分组 groups = request.user.groups.all() r2 = group and groups r3 = group in groups # 读接口大家都有权限,写接口必须为指定分组下的登陆用户 return r1 or (r2 and r3) #views.py # 游客只读,登录用户只读,只有登录用户属于 管理员 分组,才可以增删改 from utils.permissions import MyPermission class TestAdminOrReadOnlyAPIView(APIView): permission_classes = [MyPermission] # 所有用户都可以访问 def get(self, request, *args, **kwargs): return APIResponse(0, '自定义读 OK') # 必须是 自定义“管理员”分组 下的用户 def post(self, request, *args, **kwargs): return APIResponse(0, '自定义写 OK')