標籤:

Spring Security(三) -- JWT驗證原理(上)

作者: 屈定的博客n原文地址: mrdear.cn

JWT實際上與Spring Security沒多大關係,本文打算使用Spring Security配合JWT這種方式完成用戶的認證和授權.

JSON Web Token(JWT),是一個開放安全的行業標準,用於多個系統之間傳遞安全可靠的信息.關於其解釋可以參考博文:

JSON Web Token - 在Web應用間安全地傳遞信息

因為原作者寫的很詳細,這裡就只說下個人認為比較重要的問題.

JWT是什麼樣子的結構?

JSON Web Token說到底也是一串token,其形式分三段,看下圖,紅色的為Header,指定token類型與簽名類型,紫色的為請求體,存儲用戶id等關鍵信息,最後藍色的為簽名,保證整個信息的完整性,可靠性.

其中playload中可以

  • iss: 該JWT的簽發者
  • sub: 該JWT所面向的用戶
  • aud: 接收該JWT的一方
  • exp(expires): 什麼時候過期,這裡是一個Unix時間戳
  • iat(issued at): 在什麼時候簽發的
  • nbf: 定義在什麼時間之前,該jwt都是不可用的.
  • jti: jwt的唯一身份標識,主要用來作為一次性token,從而迴避重放攻擊。

JWT是一個怎樣的流程?

  1. 客戶端使用賬戶密碼請求登錄介面
  2. 登錄成功後返回JWT
  3. 客戶端再次請求其他介面時帶上JWT
  4. 服務端接收到JWT後驗證簽名的有效性.

JWT解決了什麼問題?

token被劫持

一開始理解很容易陷入一個誤區,比如有人會問對於JWT來說,jwt被劫持了的話,那麼對方就可以偽造請求,這東西怎麼能保證安全呢?

這裡問題是沒理解好JWT,JWT解決的是認證與授權的問題,上述劫持或者類似的中間人攻擊是JWT不可避免的,也是其他認證與授權方式不可避免的,想避免可以使用HTTPS,或者簽發jwt的時候記錄下Client的ip地址,這些就和JWT沒關係了.

與Session的區別

session實際上是基於cookie來傳輸的,最重要的session信息是存儲在伺服器的,所以伺服器每次可以通過cookie中的sessionId獲取到當前會話的用戶,對於單台伺服器這樣做沒問題,但是對於多台就涉及到共享session的問題了,而且認證用戶的增多,session會佔用大量的伺服器內存.

那麼jwt是存儲在客戶端的,伺服器不需要存儲jwt,jwt裡面有用戶id,伺服器拿到jwt驗證後可以獲得用戶信息.也就實現了session的功能,但是相比session,jwt是無狀態的,其不與任何機器綁定,只要簽名秘鑰足夠的安全就能保證jwt的可靠性.

JWT下服務端認為什麼樣子的請求是可信的?

對於服務端來說,無法確定下一個請求是哪一個用戶,哪一個終端發出,所以其需要一些信息定位到該用戶或者該機器,對於JWT來說其Playload裡面存儲著UserId,那麼服務端接收到Token後對其進行簽名驗證,驗證成功,則認為其是可信的,然後通過UserId從DB或者Cache中查詢出來用戶信息.

為什麼JWT能保證信息傳輸的安全可靠?

比如現在有token

eyJhbGciOiJIUzI1NiJ9.neyJleHAiOjE0OTg0ODIxNTQsInN1YiI6InF1ZGluZyIsInVzZXJJZCI6IjEwMzc5NDAxIiwicm9sZSI6ImFkbWluIn0.n-YFTYJ6FLlIQqD4G3hYcWvYlYE8H9eAA2369WEcJFVY

Headern{n "alg": "HS256"n}nPlayloadn{n "exp": 1498482154,n "sub": "quding",n "userId": "10379401",n "role": "admin"n}nSignnYFTYJ6FLlIQqD4G3hYcWvYlYE8H9eAA2369WEcJFVYn

假設我的playload被其他人劫持了,其他人把userId修改為他自己的,比如123456,但是其沒有簽名的秘鑰,所以他就沒法生成簽名.

服務端收到該Token後,會用先Base64解碼出來相應的信息,然後重新生成sign,使用該sign與客戶端傳來的Sign進行對比,一樣則證明沒被修改,也就是可信的請求,否則拒絕該請求.

下一篇開始實戰.

知乎編輯器貌似做了一次升級,修復了用戶體驗較好的bug與bug過少的bug,游標亂竄,寫不下去了,第四篇實戰請看我的博客 mrdear.cn


推薦閱讀:

【spring指南系列】計劃任務
Spring Boot 整合 Redis 實現緩存操作
Spring探秘,妙用BeanPostProcessor
史上最簡單的SpringCloud教程: docker部署spring cloud項目

TAG:Spring |