什麼是JWTweb
Json web token (JWT), 是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準((RFC 7519).該token被設計爲緊湊且安全的,特別適用於分佈式站點的單點登陸(SSO)場景。JWT的聲明通常被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也能夠增長一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。算法
起源瀏覽器
提及JWT,咱們應該來談一談基於token的認證和傳統的session認證的區別。安全
傳統的session認證服務器
咱們知道,http協議自己是一種無狀態的協議,而這就意味着若是用戶向咱們的應用提供了用戶名和密碼來進行用戶認證,那麼下一次請求時,用戶還要再一次進行用戶認證才行,由於根據http協議,咱們並不能知道是哪一個用戶發出的請求,因此爲了讓咱們的應用能識別是哪一個用戶發出的請求,咱們只能在服務器存儲一份用戶登陸的信息,這份登陸信息會在響應時傳遞給瀏覽器,告訴其保存爲cookie,以便下次請求時發送給咱們的應用,這樣咱們的應用就能識別請求來自哪一個用戶了,這就是傳統的基於session認證。cookie
可是這種基於session的認證使應用自己很可貴到擴展,隨着不一樣客戶端用戶的增長,獨立的服務器已沒法承載更多的用戶,而這時候基於session認證應用的問題就會暴露出來.網絡
基於session認證所顯露的問題session
Session: 每一個用戶通過咱們的應用認證以後,咱們的應用都要在服務端作一次記錄,以方便用戶下次請求的鑑別,一般而言session都是保存在內存中,而隨着認證用戶的增多,服務端的開銷會明顯增大。app
擴展性: 用戶認證以後,服務端作認證記錄,若是認證的記錄被保存在內存中的話,這意味着用戶下次請求還必需要請求在這臺服務器上,這樣才能拿到受權的資源,這樣在分佈式的應用上,相應的限制了負載均衡器的能力。這也意味着限制了應用的擴展能力。負載均衡
CSRF: 由於是基於cookie來進行用戶識別的, cookie若是被截獲,用戶就會很容易受到跨站請求僞造的攻擊。
基於token的鑑權機制
基於token的鑑權機制相似於http協議也是無狀態的,它不須要在服務端去保留用戶的認證信息或者會話信息。這就意味着基於token認證機制的應用不須要去考慮用戶在哪一臺服務器登陸了,這就爲應用的擴展提供了便利。
流程上是這樣的:
用戶使用用戶名密碼來請求服務器
服務器進行驗證用戶的信息
服務器經過驗證發送給用戶一個token
客戶端存儲token,並在每次請求時附送上這個token值
服務端驗證token值,並返回數據
這個token必需要在每次請求時傳遞給服務端,它應該保存在請求頭裏, 另外,服務端要支持CORS(跨來源資源共享)策略,通常咱們在服務端這麼作就能夠了Access-Control-Allow-Origin: *。
那麼咱們如今回到JWT的主題上。
JWT長什麼樣?
JWT是由三段信息構成的,將這三段信息文本用.連接一塊兒就構成了Jwt字符串。就像這樣:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
JWT的構成
第一部分咱們稱它爲頭部(header),第二部分咱們稱其爲載荷(payload, 相似於飛機上承載的物品),第三部分是簽證(signature).
加密
import jwt #只能對pyhton字典類型進行加密 第一個參數爲須要加密的數據 第二個參數爲密鑰 第三個參數爲加密算法 encoded_jwt = jwt.encode({'name':'你好'},'secret_key',algorithm='HS256') print(encoded_jwt) #加密後是一個二進制的數據 #結果>b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiXHU0ZjYwXHU1OTdkIn0.V3flV6UF3Hz0bCqzRTEs_1G46OAOuEM-ku22F14RJL4'
解密
import jwt # 解密 第一個參數爲須要解密的數據 第二個參數爲密鑰(密鑰輸入錯誤會報錯) 第三個參數爲所用的加密算法 de_code = jwt.decode(encoded_jwt,'secret_key',algorithms=['HS256']) print(de_code) #結果> {'name':'你好'}
接口實例
#定義驗證接口 def auth_required(): def decorator(view_func): def _wrapped_view(self,request, *args, **kwargs): import jwt encoded_jwt = jwt.encode({'username':'adimn'},'secret_key',algorithm='HS256') try: de_code = jwt.decode(encoded_jwt,'secret_key',algorithms=['HS256']) except Exception as e: return HttpResponse('沒權限') return view_func(self,request, *args, **kwargs) # mystr = 0 # if mystr: # return view_func(self,request, *args, **kwargs) # else: # return HttpResponse('沒權限') return _wrapped_view return decorator class MyTest(View): @auth_required() def get(self,request): return HttpResponse('123')