JSON Web 令牌(JWT)是如何保護 API 的?

原文鏈接:https://learnku.com/laravel/t/40490

討論請前往專業(yè)的 Laravel 開發(fā)者論壇:https://learnku.com/Laravel

image

你可以已經(jīng)聽說過 JSON Web Token (JWT) 是目前用于保護 API 的最新技術。

與大多數(shù)安全主題一樣,如果你打算使用它,那很有必要去了解它的工作原理(一定程度上)。問題在于,對 JWT 的大多數(shù)解釋都是技術性的,這一點讓人很頭疼。

讓我們看下,我能否解釋清楚 JWT 是如何在不引起你的注意下保護您的 API !

API 驗證

** 某些 API 資源需要限制訪問** 。例如,我們不希望一個用戶能夠更改另一個用戶的密碼。

這就是為什么我們保護某些資源,使用戶在允許訪問之前提供他的 ID 和密碼——換句話說,我們對它們進行身份驗證。

保護HTTP API的困難在于請求是 無狀態(tài)的 —— API 無法知道是否有兩個請求來自同一用戶。

那么,為什么不要求用戶在每次調(diào)用 API 時提供其 ID 和密碼呢?僅因為那將是可怕的用戶體驗。

JSON Web Token

我們需要的是一種允許用戶僅提供一次其憑證,隨后在后續(xù)請求中由服務器以另一種方式標識的方式。

為此設計了幾種系統(tǒng),當前的最新標準是 JSON Web Token。

這是一篇 關于該主題的精彩文章 ,它很好地比喻了 JSON Web Token 的工作方式:

想象一下你要入住酒店,而不是一個 API ?!窽oken」是塑料酒店安全卡,可用于進入你的房間和使用酒店設施,但不能進入任何其他人的房間。

當你退房的時候,你交回卡片。這類似于注銷。

Token 的結構

通常, JSON Web Token 是通過 HTTP 請求頭發(fā)送的。類似如下:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U

實際上, Token 部分是「Authorization: Bearer」之后的部分,僅是 HTTP 頭信息。

在你斷定這是難以理解的胡言亂語前,有幾件事你很容易注意到。

首先,Token是由三個不同的字符串組成,以句點分隔。這三個部分是 Base64 編碼 后的內(nèi)容,并且分別對應 Header , Payload 以及 Signature。

// Header eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

// Payload eyJzdWIiOiIxMjM0NTY3ODkwIn0

// Signature dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U

注意: Base64 是一種轉(zhuǎn)換字符串的方法,以確保在跨網(wǎng)絡傳輸期間不會被弄亂。這不是一種加密方式,任何人都可以 輕松解碼 以查看原始數(shù)據(jù)

我們可以對這些字符串進行解碼,以更好地了解JWT的結構。

Header

以下是 Token 中的已解碼 Header 部分。Header 是 Token 的元信息。它并沒有告訴我們很多幫助你建立基本理解的知識,因此我們不會對此進行任何詳細介紹。

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

Payload

Payload 能引起更多的關注。如果你想, Payload 可以包含任何數(shù)據(jù),但是如果 Token 的目的是 API 訪問身份驗證,則可以僅包含用戶 ID 。

{ 
  "userId": "1234567890" 
}

請注意, Payload 不安全 。 任何人都可以解碼 Token ,并確切了解 Payload 中的內(nèi)容。因此,我們通常會包含一個 ID ,而不是諸如用戶電子郵件之類的敏感識別信息。

即使 Payload 是在 API 上識別用戶所需要的全部,它也不能提供身份驗證的方法。如果其中包含所有內(nèi)容,則有人可以輕松找到你的用戶 ID 并偽造 Token 。

因此,這使我們進入了 Signature 部分,這是認證 Token 的關鍵部分。

哈希算法

在解釋簽名如何工作之前,我們需要定義什么是哈希算法。

首先,它是一個將字符串轉(zhuǎn)換為稱為 Hash 的新字符串的函數(shù)。例如,假設我們要對字符串「Hello, world」進行哈希處理。這是我們使用 SHA256 哈希算法得到的輸出:

4ae7c3b6ac0beff671efa8cf57386151c06e58ca53a78d83f36107316cec125f

哈希的最重要屬性是 你無法通過哈希算法來查看 Hash 的原始文本 。

有許多不同類型的哈希算法,但 SHA256 通常與 JWT 一起使用。

換句話說,我們不能根據(jù)上面的散列值算出原始字符串是 Hello,world。哈希非常復雜,以至于無法猜測原始字符串。

JWT 簽名

回到 JWT 結構,來看一下令牌的第三部分,簽名。實際上需要計算:

HMACSHA256( 
  base64UrlEncode(header) + "." + base64UrlEncode(payload), 
  "secret string"
);

下面是對這里發(fā)生的情況做解釋:

首先, HMACSHA256 是哈希函數(shù)的名稱, 并帶有兩個參數(shù):要散列的字符串,以及「secret」。

其次,我們哈希的字符串是 base 64 的編碼報頭,加上 base 64 的編碼有效載荷。

第三, secret 是任意一段字符串,只有服務器知道。

問. 為什么在簽名散列中包含標頭和有效負載?

這確保了簽名對于此特定令牌是唯一的。*

問. secret 是什么?

為了回答這個問題,讓我們考慮一下如何偽造令牌。

我們之前說過,您無法通過查看輸出來確定哈希的輸入。但是,由于我們知道簽名包括標頭和有效負載,因為它們是公共信息,所以如果您知道哈希算法(提示:通常在標頭中指定),則可以生成相同的哈希。

但是只有服務器知道的秘密 * 不是 * 公共信息。將其包含在哈希中可防止某人生成自己的哈希來偽造令牌。而且由于散列會掩蓋用于創(chuàng)建散列的信息,因此任何人都無法從散列中找出秘密。

*將私有數(shù)據(jù)添加到哈希中的過程稱為 * salting ,幾乎不可能破解令牌。

認證過程

因此,現(xiàn)在您對令牌的創(chuàng)建方式有了一個很好的了解。您如何使用它來驗證您的API?

登錄

用戶登錄時會生成令牌,令牌會與用戶模型一起存儲在數(shù)據(jù)庫中。

  • loginController.js *
if (passwordCorrect) { 
  user.token = generateToken(user.id); 
  user.save(); 
}

然后令牌作為authorization頭附加到登錄請求的響應中。

loginController.js

if (passwordCorrect) { 
  user.token = generateToken(user.id); 
  user.save(); 
  res.headers("authorization", `Bearer ${token}`).send(); 
}

驗證請求

現(xiàn)在,客戶端有了令牌,他們可以將其附加到任何將來的請求以身份驗證用戶。

當服務器收到帶有授權令牌的請求時,將發(fā)生以下情況:

1.它解碼令牌并從有效載荷中提取ID。

2.它使用此ID在數(shù)據(jù)庫中查找用戶。

3.它將請求令牌與用戶模型中存儲的令牌進行比較。如果它們匹配,則對用戶進行身份驗證。

authMiddleware.js

const token = req.header.token; 
const payload = decodeToken(token); 
const user = User.findById(payload.id); 
if (user.token = token) { 
  // 通過身份認證
} else {
 // 未通過身份認證
}

退出登錄

如果用戶注銷,只需刪除附加到用戶模型的令牌,現(xiàn)在令牌將不再起作用。用戶將需要再次登錄以生成新令牌。

logoutController.js

user.token = null; 
user.save();

總結

因此,這是關于如何使用 JSON Web 令牌保護 API 的最基本的說明。希望你不會很頭疼。

不過,相關的話題還有很多,所以這里有一些額外的讀物:

原文鏈接:https://learnku.com/laravel/t/40490

討論請前往專業(yè)的 Laravel 開發(fā)者論壇:https://learnku.com/Laravel

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容