Django Rest framework之權(quán)限的實現(xiàn)示例
一、權(quán)限實例
在閱讀本文之前請先參考django rest framework 之 認(rèn)證 中關(guān)于 django rest framework 的相關(guān)內(nèi)容及實例
1、目錄結(jié)構(gòu)
為了更好的管理各個功能組件,在django rest framework 之 認(rèn)證 中我們說到可以將認(rèn)證類單獨的拿出來,放到其他目錄下,然后導(dǎo)入到 views.py 文件中,在權(quán)限環(huán)節(jié)我們亦可以這么做,目錄結(jié)構(gòu)就變成這樣

在api這個app下創(chuàng)建一個utils包專門用來存放相關(guān)的組件。
2、為模型類添加認(rèn)證字段
我們在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,這樣就可以通過用戶的身份驗證不同的權(quán)限。如果想要定義一個視圖類,這個類中的邏輯只有超級用戶才能訪問。
3、具體權(quán)限認(rèn)證
可以再utils中的 permissions.py 中這么寫
# utils/permission.py
class SVIPPremission(object):
message = "必須是SVIP才能訪問" # 這里的message表示如果不通過權(quán)限的時候,錯誤提示信息
def has_permission(self,request,view):
if request.user.user_type != 3:
return False
return True
class MyPremission(object):
# 這個權(quán)限類表示當(dāng)用戶為SVIP時不可通過
def has_permission(self,request,view):
if request.user.user_type == 3:
return False
return True
這里只是判斷用戶的 USER_TYPE 的字段,判斷用戶是否有權(quán)限,也可以添加其他的邏輯進(jìn)行判斷。
4、全局配置
在上一節(jié)的django rest framework 之 認(rèn)證 的認(rèn)證中,將認(rèn)證類放到了 settings.py 文件中,這樣會作用到視圖中的每一個視圖類,如果視圖類想要自己進(jìn)行認(rèn)證,只需要重寫 authentication_classes 即可,那么對于權(quán)限來說我們也可以這么做,
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 作為測試,這里的視圖和上一節(jié)的django rest framework 之 認(rèn)證 是相接的。
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
# 當(dāng)前時間,相當(dāng)于生成一個隨機(jī)的字符串
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 = [] #里面為空,代表不需要認(rèn)證
permission_classes = [] #不里面為空,代表不需要權(quán)限
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'] = '用戶名或密碼錯誤'
#為用戶創(chuàng)建token
token = md5(user)
#存在就更新,不存在就創(chuàng)建
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):
# 用戶想要獲取訂單,就要先通過身份認(rèn)證、在全局settings.py 中已經(jīng)配置
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 中關(guān)于認(rèn)證類的配置。表示只有SVIP才能訪問這個類的內(nèi)部。
6、路由分發(fā)
在url.py中設(shè)置路由分發(fā)
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或者瀏覽器發(fā)送請求,由于我們在 setting.py 中配置了 'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.authenticate.FirstAuthenticate', 'api.utils.authenticate.MyAuthenticate'],
會對請求進(jìn)行認(rèn)證,所以要帶這用戶的 token 才能通過,進(jìn)入到權(quán)限組件。
進(jìn)入sqlite數(shù)據(jù)庫,找到對應(yīng)的注冊用戶

在數(shù)據(jù)庫中,拿到刷新的用戶的最近一次的token

拿到這個token發(fā)送請求

請求成功,則說明權(quán)限生效,也可以在將 UserInfoView 改成如下
class UserInfoView(APIView):
permission_classes = [permission.SVIPPermission]
def get(self, request, *args, **kwargs):
print(request.user)
return HttpResponse('SVIP用戶信息')
在發(fā)送請求,就會發(fā)現(xiàn)用戶不會有權(quán)限的提示信息。如下

二、源碼分析
像 django rest framework 之 認(rèn)證 一樣進(jìn)入, request 的請求流程,進(jìn)入源碼查看具體權(quán)限的操作
1、進(jìn)入dispath()方法

2、進(jìn)入initial()方法

3、進(jìn)入check_permissions()方法

4、權(quán)限類的具體操作
在這里可以看到和認(rèn)證中有類似的操作,獲取所有的權(quán)限類,并且執(zhí)行每一個權(quán)限類的 has_permission() 方法,而這個方法具體封裝了我們的判斷權(quán)限操作,但是 has_permission() 方法的返回值需要時 False 或者 True , self.permission_denied(request, message=getattr(permission, 'message', None)) 說明可以在權(quán)限類中重寫 message 屬性,來定義權(quán)限不通過時候的提示信息。

進(jìn)入 self.get_permissions() 來看一下
4、獲取所有的權(quán)限類


在APIView中有定義默認(rèn)的權(quán)限類,因此也可以通過全局配置的方法配置權(quán)限類。
5、原生的權(quán)限類
像認(rèn)證那樣, django rest framework 中也有權(quán)限類

可以根據(jù)自己的需要調(diào)用。
三、總結(jié)
權(quán)限其實的流程跟之前的認(rèn)證流程是一樣的,認(rèn)證類封裝到 request 中,然后再調(diào)用認(rèn)證類的方法,不過這里的方法返回值不再是像認(rèn)證組件那樣的直接返回一個認(rèn)證的對象,而是返回一個 True 或者 False 值表示認(rèn)證過的對象是否有某些權(quán)限再進(jìn)行具體操作。
這里注意的是,在自己重寫權(quán)限類的相關(guān)方法,添加自己的邏輯的時候,返回值需要是一個布爾值, Flase 或者 True ,表示是否有權(quán)限。也可以通過全局配置和局部配置權(quán)限類。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Django restframework 源碼分析之認(rèn)證詳解
- django基于restframework的CBV封裝詳解
- 詳解Django-restframework 之頻率源碼分析
- django rest framework 實現(xiàn)用戶登錄認(rèn)證詳解
- Django Rest framework認(rèn)證組件詳細(xì)用法
- Django Rest framework之認(rèn)證的實現(xiàn)代碼
- Django Rest framework權(quán)限的詳細(xì)用法
- Django-Rest-Framework 權(quán)限管理源碼淺析(小結(jié))
- Django restframework 框架認(rèn)證、權(quán)限、限流用法示例
相關(guān)文章
使用Python實現(xiàn)Oracle數(shù)據(jù)庫自動巡檢程序
這篇文章主要為大家詳細(xì)介紹了如何創(chuàng)建一個Oracle數(shù)據(jù)庫自動巡檢程序,以確保數(shù)據(jù)庫的順暢運行,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
Pytorch mask-rcnn 實現(xiàn)細(xì)節(jié)分享
這篇文章主要介紹了Pytorch mask-rcnn 實現(xiàn)細(xì)節(jié)分享,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06
Django1.7+python 2.78+pycharm配置mysql數(shù)據(jù)庫教程
原本感覺在Django1.7+python 2.78+pycharm環(huán)境下配置mysql數(shù)據(jù)庫是件很容易的事情,結(jié)果具體操作的時候才發(fā)現(xiàn),問題還是挺多的,這里記錄一下最終的配置結(jié)果,給需要的小伙伴參考下吧2014-11-11
python中l(wèi)ogging包的使用總結(jié)
本篇文章給大家詳細(xì)講述了python中l(wèi)ogging包的使用的相關(guān)知識點以及原理分析,有興趣的朋友可以參考學(xué)習(xí)下。2018-02-02
Python獲取CPU、內(nèi)存使用率以及網(wǎng)絡(luò)使用狀態(tài)代碼
這篇文章主要介紹了Python獲取CPU使用率、內(nèi)存使用率、網(wǎng)絡(luò)使用狀態(tài)的相關(guān)代碼,對此有需要的朋友一起測試下。2018-02-02

