一、概念
Authentication即驗(yàn)證,Permissions即權(quán)限。
Authentication驗(yàn)證是將傳入請(qǐng)求與一組標(biāo)識(shí)憑據(jù)(例如請(qǐng)求來自的用戶或用于簽名的令牌)相關(guān)聯(lián)的機(jī)制。然后,Permissions權(quán)限決定了是否應(yīng)該授予或拒絕訪問請(qǐng)求。
這里一定要注意,只配置了Authentication,接口依然是可以訪問的。決定接口是否能夠訪問需要與Permissions一起配置。
二、Authentication
1、設(shè)置驗(yàn)證方案的3種方式:
(1)在settings中設(shè)置全局默認(rèn)身份驗(yàn)證方案DEFAULT_AUTHENTICATION_CLASSES:

(2)使用裝飾器,在基于函數(shù)的視圖上設(shè)置身份驗(yàn)證方案:

(3)使用APIView基于類的視圖在每個(gè)視圖或每個(gè)視圖集的基礎(chǔ)上設(shè)置身份驗(yàn)證方案:

2、身份認(rèn)證類
(1)基本認(rèn)證:BasicAuthentication
(2)會(huì)話認(rèn)證:SessionAuthentication
(3)令牌認(rèn)證:TokenAuthentication
首先,在APP中增加rest_framework.authtoken,如圖:

第二,執(zhí)行命令python manage.py migrate同步數(shù)據(jù)庫表,auth_user表是django框架生成的用戶表,接下來就使用這個(gè)表來保存用戶的信息;authtoken_token表是和用戶登錄認(rèn)證相關(guān)的數(shù)據(jù)表,用來存放用戶token。

第三,我們創(chuàng)建一個(gè)用戶,用于后期的登錄測(cè)試,執(zhí)行命令:python manage.py createsuperuser,創(chuàng)建成功后auth_user表就有了剛剛創(chuàng)建的數(shù)據(jù)。
接下來,我們來實(shí)現(xiàn)這個(gè)登錄接口,編寫views.py:

配置urls.py:

大家自行用接口測(cè)試工具提交post請(qǐng)求到登錄接口,我這邊就使用了DRF自帶的界面操作:

因?yàn)槭鞘状蔚卿?,所以?huì)為該用戶創(chuàng)建token,即authtoken_token會(huì)產(chǎn)生一條記錄:

到這里就完成了登錄認(rèn)證,大家可以用接口測(cè)試工具測(cè)試,如果請(qǐng)求頭中不包含該token,那么無法獲取到數(shù)據(jù):

如果請(qǐng)求頭中包含token,以字符串文字“Token”為前綴,用空格分隔兩個(gè)字符串。例如:請(qǐng)求頭的格式:"Authorization":"Token XXXXXXXXXXXXXXXXXXXXXXXX"

(4)第三方包DRF-JWT
JWT:json web tokens,采用json格式在web上傳輸?shù)恼J(rèn)證字符串。
DRF中對(duì)應(yīng)的JWT包為:django-rest-framework-jwt,安裝pip install djangorestframework-jwt,增加認(rèn)證配置:

在項(xiàng)目的urls.py中配置:

編寫views.py:

測(cè)試一下,成功:

前端的其他請(qǐng)求,需要在請(qǐng)求頭中加入token,格式如下:"Authorization":"JWT <token>",如果希望token的前綴不要是JWT,例如是Bearer,可在settings中配置JWT_AUTH,如:

注意:由于drf-jwt的登錄驗(yàn)證默認(rèn)只支持使用username。
三、Permissions
權(quán)限決定了是否應(yīng)該授予或拒絕訪問請(qǐng)求。
權(quán)限檢查總是在視圖的最開始運(yùn)行,在任何其他代碼被允許繼續(xù)之前。
權(quán)限檢查通常使用request.user和request.auth屬性中的身份驗(yàn)證信息來確定是否應(yīng)允許傳入請(qǐng)求。
1、設(shè)置權(quán)限方案的3種方式
與Authentication設(shè)置一致。
2、權(quán)限類型
IsAuthenticated:最簡(jiǎn)單的權(quán)限樣式,允許任何經(jīng)過身份驗(yàn)證的用戶訪問,并拒絕任何未經(jīng)身份驗(yàn)證的用戶訪問。
IsAuthenticatedOrReadOnly:一種稍微不那么嚴(yán)格的權(quán)限樣式,允許對(duì)經(jīng)過身份驗(yàn)證的用戶進(jìn)行完全訪問,但允許對(duì)未經(jīng)身份驗(yàn)證的用戶進(jìn)行只讀訪問。
AllowAny:允許無限制訪問。
IsAdminUser:只允許管理員用戶訪問。
3、自定義權(quán)限
要實(shí)現(xiàn)自定義權(quán)限,需要覆蓋BasePermission,并實(shí)現(xiàn)以下任一方法或兩者:
(1).has_permission(self, request, view)
(2).has_object_permission(self, request, view, obj)
(3)True表示條件通過,F(xiàn)alse表示條件不通過。
四、自定義認(rèn)證與自定義權(quán)限的使用
由于drf-jwt是基于django自帶的認(rèn)證系統(tǒng)(庫中的auth_user表)來實(shí)現(xiàn)的,我自己的庫的Users表是沒有username字段的,且登錄驗(yàn)證使用字段user_no和password,所以使用pyjwt實(shí)現(xiàn)了令牌認(rèn)證,如圖,根據(jù)user_no與password生成token:

views.py中登錄的token生成使用get_jwt_token方法:

生成了token之后,怎么樣才能讓其他接口都走這個(gè)JWT的驗(yàn)證機(jī)制呢?
1、自定義認(rèn)證
參照官方文檔:要實(shí)現(xiàn)自定義身份驗(yàn)證方案,需繼承BaseAuthentication類,并使用authenticate(self, request)方法,返回user, auth。如圖,新建一個(gè)myauth.py文件,這里寫的比較簡(jiǎn)單,還可以加上驗(yàn)證token是否過期等:

配置自定義認(rèn)證,我這里使用的是全局配置的方式,在settings中配置:

2、自定義權(quán)限
用戶認(rèn)證完成后,需要配置權(quán)限,權(quán)限決定了請(qǐng)求是否能夠通過,要求任何經(jīng)過身份驗(yàn)證的用戶都訪問,但是拒絕任何未經(jīng)身份驗(yàn)證的用戶訪問。由于Users表是使用我自己創(chuàng)建的表,使用默認(rèn)的權(quán)限('rest_framework.permissions.IsAuthenticated')會(huì)報(bào)錯(cuò):not request.user.is_authenticated,所以使用自定義的權(quán)限。
新建一個(gè)myperm.py文件,寫的比較簡(jiǎn)單:

配置自定義權(quán)限,我這里也是使用的是全局配置的方式,在settings中配置:

以上,就完成了一個(gè)項(xiàng)目最基礎(chǔ)的驗(yàn)證和權(quán)限。
可以使用接口測(cè)試工具測(cè)試一下,先POST登錄接口,獲取JWT,在使用該用戶的JWT訪問其他接口,就可以獲取到數(shù)據(jù)。
如果請(qǐng)求頭中沒有攜帶JWT或者JWT錯(cuò)誤,是無法獲取到數(shù)據(jù)的。