認證是幹嗎的已經不須要多說。而先後端未分離的認證基本是用cookie或者session,先後端分離的通常用token數據庫
先建立一個django項目,項目名爲drfversion,app名爲DRF,設置簡單的數據庫表,並遷移:django
model:後端
view:cookie
url:session
啓動項目,訪問測試,先建立一個用戶root,密碼123: app
寫入一個認證類,讀源碼可知,自定義的認證類必需要定義這個方法:前後端分離
在項目根目錄建立一個utils文件夾,建立auth文件,定義一個認證類,必須繼承BaseAuthentication,注意個人代碼獲取token是經過url的條件而得,經過request.query_params獲取:
ide
一樣,要應用此認證類,讀源碼可知,須要在配置文件裏做以下配置:post
重啓項目測試:測試
第一次,沒有帶值
從數據庫中複製該token值再次測試:
跳轉到其餘網頁查看:
login登陸頁面也能夠:
可是按開發邏輯,登陸頁面不該該驗證token對吧?還沒登陸怎麼能有token呢?是吧,因此不帶token:
可是不帶token此時又提示必需要帶,因此這就是全局認證的弊端
先在配置文件裏註釋掉全局認證:
在視圖類裏導入自定義的認證類,在須要認證的視圖類添加一個類屬性 :authentication_classes = [自定義認證類名,]
其餘都不用修改,啓動測試:
登陸頁面:
test頁面,不帶token:
test頁面,帶上token:
看了源碼,其實還有不少DRF自帶的認證類,都在rest_framework.authentication裏面,也能夠根據需求直接選用DRF自帶的認證類
以上項目主要的代碼:
根url:
from django.contrib import admin from django.urls import path, re_path, include urlpatterns = [ path('admin/', admin.site.urls), re_path(r'auth/', include(('DRF.urls'))), ]
app下url:
from django.urls import path, re_path from DRF.views import DemoView, LoginView, TestView urlpatterns = [ path(r'', DemoView.as_view()), re_path(r'^login/', LoginView.as_view()), re_path(r'^test/', TestView.as_view()), ]
view:
from rest_framework.views import APIView from rest_framework.views import Response from utils.auth import MyAuth from DRF.models import User import uuid class DemoView(APIView): def get(self, request): return Response('簡單認證') class LoginView(APIView): def get(self, request): return Response('請登陸,若是沒有帳號請建立') def post(self, request): user = request.data.get('user') pwd = request.data.get('pwd') token = uuid.uuid4() User.objects.create(user=user, pwd=pwd, token=token) return Response('建立用戶成功') class TestView(APIView): authentication_classes = [MyAuth,] def get(self, request): return Response('認證測試')
model:
from django.db import models # Create your models here. class User(models.Model): user = models.CharField(max_length=32, verbose_name='用戶名', null=True, blank=True) pwd = models.CharField(max_length=32, verbose_name='密碼', null=True, blank=True) token = models.UUIDField()
auth:
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from DRF.models import User class MyAuth(BaseAuthentication): def authenticate(self, request): # 認證token token = request.query_params.get('token') if not token: raise AuthenticationFailed('沒有攜帶token') user_obj = User.objects.filter(token=token) if not user_obj: raise AuthenticationFailed('非法用戶') return (user_obj, token)
settings:
REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS": "utils.version.MyVersion", "DEFAULT_VERSION": "v1", "ALLOWED_VERSIONS": "v1, v2", "VERSION_PARAM": "ver", # "DEFAULT_AUTHENTICATION_CLASSES": ["utils.auth.MyAuth", ] }
- 自定義類,必須繼承DRF定義好的認證類,須要用什麼就繼承什麼,且根據繼承的類不一樣,必需要定義該基類裏明確規定須要的方法或者屬性
- 全局認證直接在配置文件裏的REST_FRAMEWORK裏配置字段"DEFAULT_AUTHENTICATION_CLASSES": ["自定義認證類", ],配置全局認證即表示每一個頁面都要驗證
- 局部認證直接在須要認證的視圖類添加屬性authentication_classes = [自定義認證類名,]
- 認證能夠再url添加條件參數,能夠再請求頭,能夠再請求體,根據認證類的認證類型,在認證時作不一樣的處理