问题:不一样的视图赋予不一样的权限,以用来访问python
views.pydjango
from django.shortcuts import render, HttpResponse from django.http import JsonResponse from rest_framework.views import APIView from api import models ORDER_DICT = { 1: { 'name': 'qiu', 'age': 18, 'gender': '男', 'content': '...' }, 2: { 'name': 'xi', 'age': 19, 'gender': '男', 'content': '.....' } } def md5(user): import hashlib import time ctime = str(time.time()) m = hashlib.md5(bytes(user, encoding='utf-8')) m.update(bytes(ctime, encoding='utf-8')) return m.hexdigest() class AuthView(APIView): authentication_classes = [] def post(self, request, *args, **kwargs): ret = {'code': 1000, 'msg': None} try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UerInfo.objects.filter(username=user, password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = '用户名或密码错误' # 为登陆用户建立token else: token = md5(user) # 存在就更新, 不存在就建立 models.UserToken.objects.update_or_create(user=obj, defaults={'token': token}) ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = '请求异常' return JsonResponse(ret) class OrderView(APIView): ''' 订单相关业务(只有SVIP用户有权限) ''' def get(self, request, *args, **kwargs): # 为其添加权限,当为SVIP用户才能够访问 if request.user.user_type != 3: return HttpResponse('无权访问') ret = {'code': 1000, 'msg': None, 'data': None} try: ret['data'] = ORDER_DICT except Exception as e: pass return JsonResponse(ret) class UserInfoView(APIView): ''' 用户中心(普通用户、VIP有权限) ''' def get(self, request, *args, **kwargs): print(request.user) return HttpResponse('用户信息')
当 user_type
为 1 时,发送 GET 请求,获得无权访问api
若将 user_type
换为 3,则可以访问数据app
上面每一个不一样的视图函数都须要添加一个权限功能,能够将它定义成一个类,在使用的时候直接调用,而且与视图函数区分开,能够在 utils 下新建 permission.py函数
views.pypost
from django.shortcuts import render, HttpResponse from django.http import JsonResponse from rest_framework.views import APIView from api import models from api.utils.permission import MyPermission, MyPermission1 ORDER_DICT = { 1: { 'name': 'qiu', 'age': 18, 'gender': '男', 'content': '...' }, 2: { 'name': 'xi', 'age': 19, 'gender': '男', 'content': '.....' } } def md5(user): import hashlib import time ctime = str(time.time()) m = hashlib.md5(bytes(user, encoding='utf-8')) m.update(bytes(ctime, encoding='utf-8')) return m.hexdigest() class AuthView(APIView): authentication_classes = [] def post(self, request, *args, **kwargs): ret = {'code': 1000, 'msg': None} try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UerInfo.objects.filter(username=user, password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = '用户名或密码错误' # 为登陆用户建立token else: token = md5(user) # 存在就更新, 不存在就建立 models.UserToken.objects.update_or_create(user=obj, defaults={'token': token}) ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = '请求异常' return JsonResponse(ret) class OrderView(APIView): ''' 订单相关业务(只有SVIP用户有权限) ''' permission_classes = [SVIPPermission] def get(self, request, *args, **kwargs): ret = {'code': 1000, 'msg': None, 'data': None} try: ret['data'] = ORDER_DICT except Exception as e: pass return JsonResponse(ret) class UserInfoView(APIView): ''' 用户中心(普通用户、VIP有权限) ''' permission_classes = [MyPermission] def get(self, request, *args, **kwargs): return HttpResponse('用户信息')
permission.pyui
# -*- coding: utf-8 -*- class SVIPPermission(object): message = "必须是SVIP用户才能访问" def has_permission(self, request, view): if request.user.user_type != 3: return False return True class MyPermission(object): def has_permission(self, request, view): if request.user.user_type == 3: return False return True
权限的源码流程几乎和认证是同样的。首先从 dispatch
,而后封装 request
,来到 initial
this
def initial(self, request, *args, **kwargs): ... # 省略的内容 # Ensure that the incoming request is permitted self.perform_authentication(request) # 权限判断 self.check_permissions(request) self.check_throttles(request)
进入 check_permissions
spa
def check_permissions(self, request): """ Check if the request should be permitted. Raises an appropriate exception if the request is not permitted. """ ''' self.get_permissions,首先去 OrderView 中找,没有去父类中找 在父类中返回了权限对象的列表 ''' for permission in self.get_permissions(): if not permission.has_permission(request, self): self.permission_denied( request, message=getattr(permission, 'message', None) )
def get_permissions(self): """ Instantiates and returns the list of permissions that this view requires. """ # 对类进行实例化获得权限对象的列表 return [permission() for permission in self.permission_classes]
若是没有对 self.permission_classes
设置,默认去配置文件中查找,若是设置了就使用设置的,以前在 views.py
中设置了 permission_classes
rest
class APIView(View): ... permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES ...
也能够将其设置为全剧配置
settings.py
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.auth.FirstAuthentication', 'api.utils.auth.Authentication'], 'UNAUTHENTICATED_USER': None, 'UNAUTHENTICATED_TOKEN': None, 'DEFAULT_PERMISSION_CLASSES': ['api.utils.permission.SVIPPermission'] }
回到上一步的 check_permissions
def check_permissions(self, request): """ Check if the request should be permitted. Raises an appropriate exception if the request is not permitted. """ ''' self.get_permissions,首先去 OrderView 中找,没有去父类中找 在父类中返回了权限对象的列表 ''' for permission in self.get_permissions(): # 若是 permission.has_permission(request, self) 为 False,才走里面的代码 if not permission.has_permission(request, self): self.permission_denied( # 这里有个message,是返回给用户看的信息,能够写在本身的权限中 request, message=getattr(permission, 'message', None) )
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() raise exceptions.PermissionDenied(detail=message)
认证有内置的认证,权限也有内置的权限,所以在自定义权限的时候,为了更加规范,须要继承
permission.py
from rest_framework.permissions import BasePermission class SVIPPermission(BasePermission): message = "必须是SVIP用户才能访问" def has_permission(self, request, view): if request.user.user_type != 3: return False return True class MyPermission(BasePermission): def has_permission(self, request, view): if request.user.user_type == 3: return False return True
类,继承 BasePermission
,必须实现 has_permission
方法
返回值
全局
'DEFAULT_PERMISSION_CLASSES': ['api.utils.permission.SVIPPermission']
局部
permission_classes = [MyPermission]
请求进来走 dispatch
,先对 request
封装,而后走 initial
,先作认证,认证完成作权限,权限里面把类拿过来作列表生成式生成对象,循环每个对象,执行 has_permission
方法