是目前最流行的跨域身份驗證解決方案。git
Internet服務沒法與用戶身份驗證分開,通常過程以下:github
①用戶向服務器發送用戶名和密碼。算法
②驗證服務器後,相關數據(如用戶角色,登陸時間等)將保存在當前會話中。數據庫
③服務器向用戶返回session_id,session信息都會寫入到用戶的Cookie。django
④用戶的每一個後續請求都將經過在Cookie中取出session_id傳給服務器。json
⑤服務器收到session_id並對比以前保存的數據,確認用戶的身份。跨域
這種模式最大的問題是,沒有分佈式架構,沒法支持橫向擴展。若是使用一個服務器,該模式徹底沒有問題。可是,若是它是服務器羣集或面向服務的跨域體系結構的話,則須要一個統一的session數據庫庫來保存會話數據實現共享,這樣負載均衡下的每一個服務器才能夠正確的驗證用戶身份。服務器
站點A和站點B提供同一公司的相關服務。如今要求用戶只須要登陸其中一個網站,而後它就會自動登陸到另外一個網站。怎麼作?session
①一種解決方案是聽過持久化session數據,寫入數據庫或文件持久層等。收到請求後,驗證服務從持久層請求數據。該解決方案的優勢在於架構清晰,而缺點是架構修改比較費勁,整個服務的驗證邏輯層都須要重寫,工做量相對較大。並且因爲依賴於持久層的數據庫或者問題系統,會有單點風險,若是持久層失敗,整個認證體系都會掛掉。數據結構
②另一種靈活的解決方案:經過客戶端保存數據,而服務器根本不保存會話數據,每一個請求都被髮送回服務器。 JWT是這種解決方案的表明。
在服務器身份驗證以後,將生成一個JSON對象並將其發送回用戶,以下所示。
{'name': 'json', 'role': 'Admin', 'login_time': '2018-08-08 20:15:56'}
以後,當用戶與服務器通訊時,客戶在請求中發回JSON對象。服務器僅依賴於這個JSON對象來標識用戶。爲了防止用戶篡改數據,服務器將在生成對象時添加簽名。服務器不保存任何會話數據,即服務器變爲無狀態,使其更容易擴展。
該對象爲一個很長的字符串,字符之間經過"."分隔符分爲三個子串。注意JWT對象爲一個長字串,各字串之間也沒有換行符,此處爲了演示須要,咱們特地分行並用不一樣顏色表示了。每個子串表示了一個功能塊,總共有如下三個部分:
JWT的三個部分:JWT頭(header)、載荷(payload)、簽名(signature),將它們寫成一行以下:
①header:通常存放如何處理token的方式:加密的算法、是否有簽名等
②payload:數據的主體部分:用戶信息、發行者、過時時間等
③signature:簽名:將header、payload再結合密碼鹽總體處理一下
jwt = base64(頭部).base64(載荷).hash256(base64(頭部).base(載荷).密鑰)
base64是可逆的算法、hash256是不可逆的算法
密鑰是固定的字符串,保存在服務器
pip install djangorestframework-jwt
from django.urls import path from rest_framework_jwt.views import obtain_jwt_token urlpatterns = [ path('login/', obtain_jwt_token), ]