Json web token (JWT), 是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準((RFC 7519).該token被設計爲緊湊且安全的,特別適用於分佈式站點的單點登陸(SSO)場景。JWT的聲明通常被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也能夠增長一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。web
咱們知道,http協議自己是一種無狀態的協議,而這就意味着若是用戶向咱們的應用提供了用戶名和密碼來進行用戶認證,那麼下一次請求時,用戶還要再一次進行用戶認證才行,由於根據http協議,咱們並不能知道是哪一個用戶發出的請求,因此爲了讓咱們的應用能識別是哪一個用戶發出的請求,咱們只能在服務器存儲一份用戶登陸的信息,這份登陸信息會在響應時傳遞給瀏覽器,告訴其保存爲cookie,以便下次請求時發送給咱們的應用,這樣咱們的應用就能識別請求來自哪一個用戶了。算法
HTTP Basic Auth簡單點說明就是每次請求API時都提供用戶的username和password,簡言之,Basic Auth是配合RESTful API 使用的最簡單的認證方式,只需提供用戶名密碼便可,但因爲有把用戶名密碼暴露給第三方客戶端的風險,在生產環境下被使用的愈來愈少。所以,在開發對外開放的RESTful API時,儘可能避免採用HTTP Basic Auth。數據庫
OAuth(開放受權)是一個開放的受權標準,容許用戶讓第三方應用訪問該用戶在某一web服務上存儲的私密的資源(如照片,視頻,聯繫人列表),而無需將用戶名和密碼提供給第三方應用。json
OAuth容許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。每個令牌受權一個特定的第三方系統(例如,視頻編輯網站)在特定的時段(例如,接下來的2小時內)內訪問特定的資源(例如僅僅是某一相冊中的視頻)。這樣,OAuth讓用戶能夠受權第三方網站訪問他們存儲在另外服務提供者的某些特定信息,而非全部內容
下面是OAuth2.0的流程:瀏覽器
Cookie認證機制就是爲一次請求認證在服務端建立一個Session對象,同時在客戶端的瀏覽器端建立了一個Cookie對象;經過客戶端帶上來Cookie對象來與服務器端的session對象匹配來實現狀態管理的。默認的,當咱們關閉瀏覽器的時候,cookie會被刪除。但能夠經過修改Cookie 的expire time使cookie在必定時間內有效;
緩存
JWT (Json Web Token)是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準。安全
JWT的聲明通常被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源。好比用在用戶登陸上。服務器
有些朋友可能會認爲,我登陸只須要用緩存或者數據庫記錄下一個特徵碼或者是Cookies就能夠了,爲何要使用JWT呢?咱們知道一個數據庫或者是一個軟件,損耗時間最大的地方就是咱們的 I/O(輸入輸出,一般指的就是硬盤的讀寫),所以咱們選擇解碼一次HS256,對於如今的計算能力強大的計算機而言,解一次HS256比訪問一次磁盤要快得多。cookie
基於token的鑑權機制相似於http協議也是無狀態的,它不須要在服務端去保留用戶的認證信息或者會話信息。這就意味着基於token認證機制的應用不須要去考慮用戶在哪一臺服務器登陸了,這就爲應用的擴展提供了便利。
流程上是這樣的:
網絡
這個token必需要在每次請求時傳遞給服務端,它應該保存在請求頭裏, 另外,服務端要支持CORS(跨來源資源共享)策略,通常咱們在服務端這麼作就能夠了Access-Control-Allow-Origin: *。
那麼咱們如今回到JWT的主題上。
咱們先來看一段jwt
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
仔細觀察咱們能夠發現這一段字符串中含有兩個 " . ",這兩個 " . "把jwt分紅了三份,咱們分別成爲頭部、荷載信息、簽證信息。那麼這三部分的分工是什麼呢?
JWT的頭部承載了兩個信息
完整的頭部應該是像這樣的一個Json
{ 'typ': 'JWT', 'alg': 'HS256' }
將頭部Json進行base64加密就獲得了咱們的第一部分
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
第二部分是荷載信息,Payload,你能夠理解爲咱們的JWT是一輛大倉庫,第一部分頭部就是倉庫的名稱編號等基礎信息,而荷載信息就是倉庫的自己,包含了倉庫裏面的全部貨物。這些信息又包含了三個部分:
iss: jwt簽發者
sub: jwt所面向的用戶
aud: 接收jwt的一方
exp: jwt的過時時間,這個過時時間必需要大於簽發時間
nbf: 定義在什麼時間以前,該jwt都是不可用的.
iat: jwt的簽發時間
jti: jwt的惟一身份標識,主要用來做爲一次性token,從而回避重放攻擊。
公共的聲明能夠添加任何的信息,通常添加用戶的相關信息或其餘業務須要的必要息。但不建議添加敏感信息,由於該部分在客戶端可解密。
私有聲明是提供者和消費者所共同定義的聲明,通常不建議存放敏感信息,由於base64是對稱解密的,意味着該部分信息能夠歸類爲明文信息。
事實上咱們的Header和Payload都是基於base64加密的,這種密文都是能夠對稱解密的,所以請不要存放敏感信息。
定義一個payload:
{ "sub": "1234567890", "name": "John Doe", "admin": true }
進行base64加密後,獲得了咱們的第二部分
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
Jwt的第三部分是一個簽證信息,這個簽證信息由三部分組成:
這一部分能夠理解爲對前部分的一個校驗,將前兩部分加密後的密文經過在Header中定義的加密方式,與服務端所傳入的密鑰進行一次加密,假如前兩部分的信息被篡改的話,必然通不過最後一部分簽證的校驗。所以經過這樣保證了Jwt的安全性。
所以,保存並隱藏好咱們的加密密鑰是很是重要的,假設泄露了,就意味着任何知道密鑰的人均可以輕鬆的對jwt進行自我簽發和驗證。
若是個人文章幫到了你,請幫忙點個贊,點個關注。謝謝!