使用 JWT 和 Logto 保護你的 Express.js API
學習如何使用 JSON Web Tokens (JWT) 和 Logto 保護你的 Express.js API 端點。
介紹
當你開發一個網頁應用程式時,保護你的 API 端點不被未授權訪問是非常重要的。想像一下你正在建立一個在線購物網站;你絕對不希望網絡竊賊利用你的 API。
假設你已經建立了一個具備用戶認證的 Express.js 應用程式,要求用戶在執行某些操作之前先登錄。如果沒有,你可以使用 Logto 開始你的旅程。只需幾行代碼即可建立用戶認證流程。
然而,即使在用戶認證之後,你仍面臨著各種選擇來保護你的 API 端點。不幸的是,大多數選擇都有其缺點:
- 基於會話的認證:將你的 API 綁定到會話存儲,這不具可擴展性並且不適合微服務。
- 調用認證服務:這會增加額外的網絡調用,增大延遲和成本。一些認證服務甚至根據 API 調用量收費,可能導致高額費用。
在本教程中,我們將演示如何使用 JSON Web Tokens (JWT) 和 Logto 來強化你的 API 端點。這種方法提供了可擴展性和最小的額外成本。
先決條件
在繼續之前,請確保你擁有以下內容:
- 一個 Logto 帳戶。如果你還沒有,你可以免費註冊。
- 一個需要 API 保護的 Express.js 專案和一個消費 API 的客戶端應用程式。
- 基本熟悉 JSON Web Token (JWT)。
在 Logto 中定義你的 API 資源
Logto 完全利用 RFC 8707: OAuth 2.0 資源指示器 來保護你的 API 端點。這意味著你可以使用它們的實際 URL 定義你的 API 資源。
導航到 Logto 控制台中的「API 資源」標籤並點擊「創建 API 資源」來創建一個新的。例如,如果你想保護 /api/products
端點,你可以使用 URL https://yourdomain.com/api/products
作為標識符。
在你的客戶端應用程式中獲取訪問令牌
接下來,你需要將 Logto SDK 集成到你的客戶端應用程式中。此應用程式可能與你的 Express.js 後端不同;例如,你可能有一個使用 Express.js 作為後端 API 服務器的 React 應用程式。
你還需要調整 Logto SDK 配置,告知 Logto 你希望在此獲取訪問令牌。以下是一個使用 React 的例子:
一旦用戶使用 Logto 登錄,Logto SDK 中的 isAuthenticated
會變為 true
:
現在,你可以使用 getAccessToken
方法檢索你的 API 訪問令牌:
最後,將此訪問令牌包含在發送到你的 API 的 Authorization
頭部中:
在你的 API 中驗證訪問令牌
在你的 Express.js 應用程式中,安裝 jose
庫以進行 JWT 驗證:
由於我們使用 Bearer 認證,從 Authorization
頭部中提取訪問令牌:
隨後,創建一個中間件來驗證訪問令牌:
現在你可以使用這個中間件來保護你的 API 端點:
通過這種方法,你不需要每次請求到達時都聯繫 Logto 服務器。相反,你從 Logto 服務器获取 JSON Web Key Set (JWKS) 一次,隨後本地驗證訪問令牌。
基於角色的訪問控制
到目前為止,我們只是驗證用戶已使用 Logto 登錄。我們仍然不知道該用戶是否擁有訪問 API 端點的適當權限。這是因為 Logto 允許任何人為現有 API 資源獲得訪問令牌。
為了解決此問題,我們可以使用基於角色的訪問控制 (RBAC)。在 Logto 中,你可以定義角色並為其分配權限。查閱本教程以學習如何在 Logto 中定義角色和權限。
定義 角色和權限後,你可以在 LogtoProvider
組件中添加 scopes
選項:
然後 Logto 僅會向用戶發放具有適當作用域的訪問令牌。例如,如果用戶只有 read:products
作用域,訪問令牌將僅包含該作用域:
如果用戶同時具有 read:products
和 write:products
作用域,訪問令牌將包含以空格為分隔符的兩個作用域:
在你的 Express.js 應用程式中,你可以在授予 API 端點訪問權限之前驗證訪問令牌是否包含正確的作用域:
結論
保護 API 端點同時確保可擴展性不是件容易的事。在 Logto,我們努力為開發人員簡化請求認證,讓你能夠更專注於商業邏輯。
如有任何問題,請隨時加入我們的 Discord 服務器。我們的社群隨時樂意幫助你。