JWT-JSON Web令牌的深入介紹

in-depth-introduction-jwt-feature-image

JWT-JSON Web令牌的深入介紹

從桌面應用程序到Web應用程序或移動應用程序,身份驗證是幾乎所有應用程序中最重要的部分之一。 本教程是JWT(JSON Web令牌)的深入介紹,可幫助您瞭解:

使用Vuex和Vue路由器進行Vue.js JWT身份驗證
使用HttpInterceptor和路由器進行Angular 8 JWT身份驗證
React JWT身份驗證(無Redux)示例

使用JWT的Spring Security概述:
[按體系結構使用了 MySQL,Spring Security示例的Spring Boot JWT Auth[(https://bezkoder.com/spring-boot-jwt-mysql-spring-security-architecture/)

內容

  • 基於會話的身份驗證和基於令牌的身份驗證
  • JWT是如何工作的
  • 如何創建JWT
    • 標頭
    • 有效載荷
    • 簽名
    • 結合一切
  • JWT如何保護我們的數據
  • 服務端如何校驗從客戶端過來的JWT
  • 結論
  • 進一步閱讀

基於會話的身份驗證和基於令牌的身份驗證

對於使用任何網站,移動應用程序或桌面應用程序……您幾乎需要創建一個帳戶,然後使用該帳戶登錄以訪問該應用程序的功能。 我們稱該行爲爲身份驗證

那麼,如何驗證帳戶?
首先,我們來看看過去流行的網站使用的一種簡單方法:基於會話的身份驗證

in-depth-introduction-jwt-session-based-authentication
在上圖中,當用戶登錄網站時,服務器將爲該用戶生成一個會話並將其存儲(在內存或數據庫中)。服務器還會爲客戶端返回一個SessionId,以將其保存在瀏覽器Cookie中。

服務器上的會話具有到期時間。在此時間之後,該會話已過期,用戶必須重新登錄才能創建另一個會話。

如果用戶已登錄並且會話尚未到期,則Cookie(包括SessionId)將始終與所有向服務器的HTTP請求一起使用。服務器將比較此SessionId與存儲的會話以進行身份​​驗證並返回相應的響應。

沒關係。但是爲什麼我們需要基於令牌的身份驗證?
答案是我們不僅有網站,而且那裏有很多平臺。

假設我們有一個與Session配合良好的網站。有一天,我們想爲移動(本地應用程序)實現系統,並與當前的Web應用程序使用同一數據庫。我們應該做什麼?我們無法使用基於會話的身份驗證對使用Native App的用戶進行身份驗證,因爲這些類型沒有Cookie。

我們是否應該構建另一個支持Native Apps的後端項目?
還是應該爲Native App用戶編寫一個身份驗證模塊?

這就是基於令牌的身份驗證誕生的原因。
使用此方法,服務器會將用戶登錄狀態編碼爲JSON Web令牌(JWT),並將其發送給客戶端。 如今,許多RESTful API都在使用它。 讓我們轉到下一部分,我們將知道它是如何工作的。

JWT是如何工作的

現在看下面的流程:
in-depth-introduction-jwt-token-based-authentication
您會發現它很容易理解。 服務器沒有創建會話,而是從用戶登錄數據生成了JWT,並將其發送給客戶端。 客戶端保存JWT,從現在開始,來自客戶端的每個請求都應附加到該JWT(通常在標頭處)。 服務器將驗證JWT並返回響應。

要在客戶端存儲JWT,取決於您使用的平臺:
- 瀏覽器:Local Storage
- IOS: Keychain
- Android: SharedPreferences
這是基於令牌的身份驗證流程的概述。 在下一節中,您將更深入地瞭解它。

如何創建JWT

首先,您應該瞭解JWT的三個重要部分:

  • 標頭
  • 有效載荷
  • 簽名

標頭

標頭回答了這個問題:我們將如何計算JWT?
現在來看一個標頭示例,它是一個JSON對象,如下所示:

{
  "typ": "JWT",
  "alg": "HS256"
}

– typ是“ type”,表示此處的令牌類型是JWT。
– alg代表“算法”,它是一種用於生成令牌簽名的哈希算法。 在上面的代碼中,HS256是HMAC-SHA256 –使用密鑰的算法。

有效載荷

有效負載可幫助我們回答:我們想在JWT中存儲什麼?
這是有效負載示例:

{
  "userId": "abcd12345ghijk",
  "username": "bezkoder",
  "email": "[email protected]",
  // standard fields
  "iss": "zKoder, author of bezkoder.com",
  "iat": 1570238918,
  "exp": 1570238992
}

在上面的JSON對象中,我們存儲3個用戶字段:userId,username, email。 您可以保存所需的任何字段。

我們也有一些Standard Fields。 它們是可選的。

  • iss(Issuer):誰發行JWT
  • iat(發佈於):JWT的發佈時間:
  • exp(到期時間):JWT到期時間
    我們可以在[https://en.wikipedia.org/wiki/JSON_Web_Token#Standard_fields](https://en.wikipedia.org/wiki/JSON_Web_Token#Standard_fields]查看更多的Standard Fields

簽名

這部分是我們使用上面我告訴過您的哈希算法的地方。
查看下面獲得簽名的代碼:

const data = Base64UrlEncode(header) + '.' + Base64UrlEncode(payload);
const hashedData = Hash(data, secret);
const signature = Base64UrlEncode(hashedData);

讓我們解釋一下。
–首先,我們對Header和Payload進行編碼,並用點將它們連接起來。

data = '[encodedHeader].[encodedPayload]'

–接下來,我們使用帶有祕鑰字符串的Hash算法(在Header中定義)對數據進行哈希處理。
–最後,我們對哈希結果進行編碼以獲得簽名

結合一切

在擁有Header,Payload,Signature之後,我們將它們組合成JWT標準結構:header.payload.signature。
以下代碼將說明我們如何做到這一點。

const encodedHeader = base64urlEncode(header);
/* Result */
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"

const encodedPayload = base64urlEncode(payload);
/* Result */
"eyJ1c2VySWQiOiJhYmNkMTIzNDVnaGlqayIsInVzZXJuYW1lIjoiYmV6a29kZXIiLCJlbWFpbCI6ImNvbnRhY3RAYmV6a29kZXIuY29tIn0"

const data = encodedHeader + "." + encodedPayload;
const hashedData = Hash(data, secret);
const signature = base64urlEncode(hashedData);
/* Result */
"crrCKWNGay10ZYbzNG3e0hfLKbL7ktolT7GqjUMwi3k"

// header.payload.signature
const JWT = encodedHeader + "." + encodedPayload + "." + signature;
/* Result */
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJhYmNkMTIzNDVnaGlqayIsInVzZXJuYW1lIjoiYmV6a29kZXIiLCJlbWFpbCI6ImNvbnRhY3RAYmV6a29kZXIuY29tIn0.5IN4qmZTS3LEaXCisfJQhrSyhSPXEgM1ux-qXsGKacQ"

JWT如何保護我們的數據

JWT不保護您的數據

JWT完全不會隱藏,掩蓋和保護數據。 您可以看到,生成JWT(標頭,有效負載,簽名)的過程僅對數據進行哈希處理,而不對數據進行加密。

JWT的目的是證明數據是由真實來源生成的。

那麼,如果有中間人攻擊可以獲取JWT,然後解碼用戶信息怎麼辦? 是的,這是可能的,因此請始終確保您的應用程序具有HTTPS加密。

服務器如何從客戶端驗證JWT

在上一節中,我們使用Secret字符串創建簽名。 此Secret字符串對於每個應用都是唯一的,並且必須安全地存儲在服務器端。

從客戶端接收JWT時,服務器獲取簽名,並驗證簽名是否已通過與上述相同的算法和Secret字符串正確地進行了哈希處理。 如果它與服務器的簽名匹配,則JWT有效。

重要!

當發送給服務端時,有經驗的程序猿仍然可以添加或編輯有效載荷信息。 在這種情況下我們該怎麼辦?
我們先存儲令牌,然後再將其發送給客戶端。 它可以確保客戶端稍後發送的JWT有效。

此外,將用戶的令牌保存在服務器上還將使系統的強制註銷功能受益。

結論

永遠不會有最佳的身份驗證方法。 這取決於用例和實現方式。

但是,對於要在許多平臺上擴展爲大量用戶的應用程序,首選JWT身份驗證,因爲令牌將存儲在客戶端。

祝您學習愉快,再見!

進一步學習

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章