您好,登錄后才能下訂單哦!
一、權限實例
在閱讀本文之前請先參考django rest framework 之 認證 中關于 django rest framework
的相關內容及實例
1、目錄結構
為了更好的管理各個功能組件,在django rest framework 之 認證 中我們說到可以將認證類單獨的拿出來,放到其他目錄下,然后導入到 views.py
文件中,在權限環節我們亦可以這么做,目錄結構就變成這樣
在api這個app下創建一個utils包專門用來存放相關的組件。
2、為模型類添加認證字段
我們在models.py中定義了兩個模型類,分別是
from django.db import models class UserInfo(models.Model): USER_TYPE = ( (1,'普通用戶'), (2,'VIP'), (3,'SVIP') ) user_type = models.IntegerField(choices=USER_TYPE, default=1) username = models.CharField(max_length=32) password = models.CharField(max_length=64) class UserToken(models.Model): user = models.OneToOneField(UserInfo,on_delete=models.CASCADE) token = models.CharField(max_length=64)
在 UserInfo
中通過為用戶添加一個 user_type
字段來保證用戶的身份,是普通用戶,VIP還是SVIP,這樣就可以通過用戶的身份驗證不同的權限。如果想要定義一個視圖類,這個類中的邏輯只有超級用戶才能訪問。
3、具體權限認證
可以再utils中的 permissions.py
中這么寫
# utils/permission.py class SVIPPremission(object): message = "必須是SVIP才能訪問" # 這里的message表示如果不通過權限的時候,錯誤提示信息 def has_permission(self,request,view): if request.user.user_type != 3: return False return True class MyPremission(object): # 這個權限類表示當用戶為SVIP時不可通過 def has_permission(self,request,view): if request.user.user_type == 3: return False return True
這里只是判斷用戶的 USER_TYPE
的字段,判斷用戶是否有權限,也可以添加其他的邏輯進行判斷。
4、全局配置
在上一節的django rest framework 之 認證 的認證中,將認證類放到了 settings.py
文件中,這樣會作用到視圖中的每一個視圖類,如果視圖類想要自己進行認證,只需要重寫 authentication_classes
即可,那么對于權限來說我們也可以這么做,
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.authenticate.FirstAuthenticate', 'api.utils.authenticate.MyAuthenticate'], "UNAUTHENTICATED_USER": None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN": None,# 匿名,request.auth = None "DEFAULT_PERMISSION_CLASSES": ['api.utils.permission.MyPermission'], # 表示每一個視圖類(只要不重寫permission_classes屬性),都需要SVIP的用戶才能訪問。 }
5、視圖
在視圖 view.py
中定義一個用戶詳情類 UserInfoView
作為測試,這里的視圖和上一節的django rest framework 之 認證 是相接的。
from django.shortcuts import render, HttpResponse from django.http import JsonResponse from django.views import View from rest_framework.views import APIView from rest_framework.request import Request from .utils import authenticate, permission from api import models import json def md5(user): import hashlib import time # 當前時間,相當于生成一個隨機的字符串 ctime = str(time.time()) # token加密 m = hashlib.md5(bytes(user, encoding='utf-8')) m.update(bytes(ctime, encoding='utf-8')) return m.hexdigest() class AuthView(APIView): '''用于用戶登錄驗證''' authentication_classes = [] #里面為空,代表不需要認證 permission_classes = [] #不里面為空,代表不需要權限 def get(self, request, *args, **kwargs): ret = {'code': 1000, 'msg': 'success', 'name': '偷偷'} ret = json.dumps(ret, ensure_ascii=False) return HttpResponse(ret) def post(self,request,*args,**kwargs): ret = {'code':1000,'msg':None} try: user = request.POST.get('username') pwd = request.POST.get('password') print(user, pwd) obj = models.UserInfo.objects.filter(username=user,password=pwd).first() print(obj.username, obj.password) if not obj: ret['code'] = 1001 ret['msg'] = '用戶名或密碼錯誤' #為用戶創建token 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) ORDER_DICT = { 1:{ 'name':'apple', 'price':15 }, 2:{ 'name':'狗子', 'price':100 } } class OrderView(APIView): # 用戶想要獲取訂單,就要先通過身份認證、在全局settings.py 中已經配置 permission_classes = [] def get(self, request, *args, **kwargs): ret = { 'code': 1024, 'msg': '訂單獲取成功', } try: ret['data'] = ORDER_DICT except Exception as e: pass return JsonResponse(ret) class UserInfoView(APIView): permission_classes = [permission.SVIPPermission] def get(self, request, *args, **kwargs): print(request.user) return HttpResponse('SVIP用戶信息')
這里的 UserInfoView
重寫了 permission_classes
屬性,則不會再使用 settings.py
中關于認證類的配置。表示只有SVIP才能訪問這個類的內部。
6、路由分發
在url.py中設置路由分發
from django.conf.urls import url from api.views import AuthView, OrderView, UserInfoView urlpatterns = [ url(r'^api/v1/auth/$', AuthView.as_view()), url(r'^api/v1/order/$', OrderView.as_view()), url(r'^api/v1/info/$', UserInfoView.as_view()), ]
7、請求測試
Postman或者瀏覽器發送請求,由于我們在 setting.py
中配置了 'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.authenticate.FirstAuthenticate', 'api.utils.authenticate.MyAuthenticate'],
會對請求進行認證,所以要帶這用戶的 token
才能通過,進入到權限組件。
進入sqlite數據庫,找到對應的注冊用戶
在數據庫中,拿到刷新的用戶的最近一次的token
拿到這個token發送請求
請求成功,則說明權限生效,也可以在將 UserInfoView
改成如下
class UserInfoView(APIView): permission_classes = [permission.SVIPPermission] def get(self, request, *args, **kwargs): print(request.user) return HttpResponse('SVIP用戶信息')
在發送請求,就會發現用戶不會有權限的提示信息。如下
二、源碼分析
像 django rest framework 之 認證 一樣進入, request
的請求流程,進入源碼查看具體權限的操作
1、進入dispath()方法
2、進入initial()方法
3、進入check_permissions()方法
4、權限類的具體操作
在這里可以看到和認證中有類似的操作,獲取所有的權限類,并且執行每一個權限類的 has_permission()
方法,而這個方法具體封裝了我們的判斷權限操作,但是 has_permission()
方法的返回值需要時 False
或者 True
, self.permission_denied(request, message=getattr(permission, 'message', None))
說明可以在權限類中重寫 message
屬性,來定義權限不通過時候的提示信息。
進入 self.get_permissions()
來看一下
4、獲取所有的權限類
在APIView中有定義默認的權限類,因此也可以通過全局配置的方法配置權限類。
5、原生的權限類
像認證那樣, django rest framework
中也有權限類
可以根據自己的需要調用。
三、總結
權限其實的流程跟之前的認證流程是一樣的,認證類封裝到 request
中,然后再調用認證類的方法,不過這里的方法返回值不再是像認證組件那樣的直接返回一個認證的對象,而是返回一個 True
或者 False
值表示認證過的對象是否有某些權限再進行具體操作。
這里注意的是,在自己重寫權限類的相關方法,添加自己的邏輯的時候,返回值需要是一個布爾值, Flase
或者 True
,表示是否有權限。也可以通過全局配置和局部配置權限類。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。