繁體中文(香港)
  • migration
  • user-migration
  • migration-challenges
  • workaround

將現有的用戶數據庫遷移至 Logto 的一般指引

本文介紹如何利用現有工具將之前的用戶數據遷移至 Logto,在 Logto 尚未提供數據遷移服務的情況下。

Darcy Ye
Darcy Ye
Developer

Logto 暫時還沒有一系列的數據遷移工具,但我們已經開放了管理 API 的基本功能。用戶可以通過編寫腳本來完成現有用戶數據庫的遷移,這不會造成阻礙。

鑑於我們收到的一些來自社區用戶的需求,以及當前我們沒有文件解釋用戶數據庫遷移的具體步驟,我們在本文中作出適當的介紹,以幫助用戶找到具體思路並節省閱讀 Logto 代碼和文件的時間。

第一步:了解 Logto 的基本用戶數據結構和使用情境

Logto 使用 PostgreSQL database 作為底層架構。除了其各種性能優勢外,一個重要原因是它支持自定義 JSON/JSONB 數據類型,並允許在 JSON 類型數據的內部值上構建索引,平衡數據庫性能和可擴展性。

至於 Logto 的用戶數據結構,請參考 user reference 了解所有細節。在這裡,我們著重描述 Logto 比其他身份服務可能不同的方面。

id

這是 Logto 用戶的一個隨機生成的內部唯一標識符號。用戶在使用 Logto 基礎服務時不會注意到 id

熟悉數據庫的工程師應該不會對此感到奇怪。即使是最基本的身份系統也會有一個 id 來唯一識別用戶,儘管其形式經常有所不同。有些身份服務可能使用用戶名來唯一識別用戶。

username, primaryEmail, primaryPhone

在這裡,用戶名、主要電郵和主要電話是 Logto 與其他身份系統大相徑庭的地方——這些都可以作為終端用戶可見的唯一標識符。

在許多其他身份系統中,用戶名用於識別(用戶名不能在賬戶之間重複),這很容易理解。

但在 Logto 中,主要電郵/電話也用於區分用戶。也就是說,若用戶 A 已擁有主要電郵 [email protected],則其他用戶 B 不能將此郵箱地址作為其主要電郵。主要電話也類似。

某些其他身份系統允許使用不同的用戶名註冊多個帳戶但綁定相同的電郵/電話,這在 Logto 中是不允許的(電郵/電話可以添加到 Logto 的 customData 中)。這是因為在 Logto 中主要電郵/電話可以用於免密碼登錄。

identities

Logto 定義 identities 字段為 JSON 類型,其類型定義如下:

近年來,為方便獲取新用戶,身份系統允許用戶通過一些現有的具有大量用戶基礎的社交賬戶快速登錄,如 google / facebook,等等。

在下面的例子中,identities 字段儲存了社交登錄的信息:

在此例中,facebookgithub 是社交供應商的名稱,userId 是用於登錄的用戶社交賬戶的 iddetails 還包括一些用戶已經授權社交供應商顯示的信息,這些信息將在特定時間添加到用戶的 Logto 用戶資料中。

如果舊數據庫包含用戶所使用的社交供應商名稱(如 facebookgoogle)和 id(參見上例中的 userId),則 Logto 用戶可以直接使用同一個社交賬戶登錄。

customData

此字段可存儲任何用戶相關的信息,比如上述不能用於免密登錄的電郵/電話(可能用於接收通知或其他商業相關功能)等。

其他字段比較容易理解(除了 passwordEncryptedpasswordEncryptionMethod,這將在後續解釋),請自行閱讀文件。

第二步:編寫數據庫遷移腳本

對於大型數據庫遷移,編寫遷移腳本是最常見的方法。我們將提供一個簡單的例子來幫助理解如何編寫遷移腳本以迎合不同的需求。

需要注意的是,在編寫遷移腳本時,我們跳過了獲取原始數據的過程,因為有很多方法可以獲取數據,比如從數據庫導出到文件然後閱讀文件,或者通過 API 檢索。這些都不是遷移腳本的重點,我們在這裡不會詳細討論。

在遷移腳本中看到 tenant_id 時,你可能會感到奇怪。Logto 是基於多租戶架構設計的。對於開源 Logto(Logto OSS)用戶,你可以將用戶的 tenant_id 設置為 default

對于自我托管的 Logto OSS 用戶,獲取數據庫連接相對容易。但是,對於 Logto cloud 用戶,由於安全原因,目前我們無法提供數據庫連接權限給用戶。用戶需要參考 API Docs 並使用與用戶相關的 API 來遷移用戶。我們明白,這種方法並不適合大規模用戶數據遷移,但在此階段還是能夠處理有限用戶數據的遷移。

第三步:哈希密碼遷移挑戰及潛在解決方案

在我們之前的 blog 中,我們談到了一些防止密碼攻擊的措施。身份基礎設施提供者可以做的一件事是不以明文存儲密碼,而是保存哈希密碼。

另一篇 blog 文章 解釋了密碼哈希,我們指出哈希值是不可逆的。

第二篇博客文章還比較了一些哈希算法的演變。Logto 本身使用文章中提到的 Argon2i 算法,目前不支持其他哈希算法。這意味著使用其他哈希算法的舊用戶數據庫的密碼哈希無法直接遷移至 Logto 的數據庫。

即使 Logto 除了 Argon2i 還支持其他常用的哈希算法,鑑於鹽值在應用哈希算法時的靈活性,直接遷移舊數據依然是困難的。

除了將來支持其他哈希算法之外,Logto 也很可能提供自定義鹽值計算方法以適應不同的情況。

在此之前,你可以使用 Logto 的 sign-in experience configuration 讓用戶通過其他方式(如電郵 + 驗證碼)登錄並在進入應用程式之前填寫新密碼(將使用 Argon2i 哈希算法)。之後即可使用新密碼進行登錄。

需要注意的是,如果原始用戶數據只支持用密碼登錄,則上述的解決方案不會適用於這種場景。這是因為前面提到的解決方案是實際上是通過替代登錄方式利用 Logto 在用戶流程中提供的 "所需信息完成" 機制以解決密碼哈希不兼容問題。

因此,若原有用戶數據僅支持密碼登錄,該解決方案將無法解決這種情況,因為沒有可用的替代登錄選項。

這裡提到的解決方案並沒有真正解決哈希密碼遷移問題,而是從 Logto 產品的角度提供了替代解決方案,以便不妨礙用戶登錄你的產品。

第四步:逐步切換到 Logto 和狀態監控

完成以上步驟後,終端用戶即可通過 Logto 登錄並使用你的服務。

由於通常在遷移過程中不會中斷服務,因此同步到 Logto 的用戶數據可能不是最新的。當發現這類不常見的情況時,需要從舊數據庫同步到 Logto。

在較長時間(或應用其他已定義的指標)未發生數據不一致情況後,即可完全放棄舊數據庫。

結論

在本文中,我們介紹了一個理想數據庫遷移的步驟。

如果你遇到以上未提及的問題,歡迎加入我們的社群,或聯絡我們以示求助。你所遇到的問題也可能是其他人遇到的,將成為我們設計遷移工具時需要考慮的問題。