問題:不一樣的視圖賦予不一樣的權限,以用來訪問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
方法