SAP Commerce Cloud UI 的使用者會話管理
這是 Jerry 2021 年的第 51 篇文章,也是汪子熙公眾號總共第 328 篇原創文章。
如無特殊說明,本公眾號介紹的 SAP Commerce Cloud UI,均指新一代基於 Spartacus 開源專案開發的 UI,而非傳統的基於 JSP 技術,同 Commerce 平臺耦合在一起的 Accelerator UI.
前文 從淘寶首頁登入說起 提到過,淘寶網的使用者會話管理,通過瀏覽器的 Cookie 和伺服器端的使用者會話物件來實現。
而 SAP Commerce Cloud UI,基於 100% API 驅動的無頭電商架構,Commerce 後臺將 Commerce 核心業務通過 OCC(Omni Commerce Connect) API 的方式暴露出來。藉助這些 API 和開源的 SAP Spartacus 庫,客戶可以自行開發具備個性化 UX 的電商網站。
關於 SAP Commerce Cloud Headless 架構的更多介紹,請參考我之前的文章:Jerry在2020 SAP全球技術大會的分享:SAP Spartacus技術介紹的文字版。
SAP Commerce Cloud 有個名為 Oauth2 的 extension,基於 OAuth 2.0 協議實現了使用者認證和令牌頒發/功能,支援 OAuth 2.0 協議定義的包括 Resource Owner Password Flow 在內的全部四種認證流。
SAP Commerce Cloud UI 扮演了 OAuth 2.0 認證框架中的客戶端 (Client) 角色,通過消費 SAP Commerce Oauth2 擴充套件提供的 OAuth 系列 API,實現使用者會話管理。
讓我們從最初始的使用者登入場景說起。
輸入使用者名稱和密碼:
SAP Commerce Cloud UI 呼叫 Commerce OAuth2 API,endpoint 為 /authorizationserver/oauth/token, 將使用者名稱,密碼,client_id 和 client_secret 去換取訪問令牌(Access Token)和重新整理令牌(Refresh Token).
這裡的 SAP Commerce Cloud UI 作為 OAuth 認證體系裡的客戶端,其 client_id 和 client_secret 在 Commerce Backoffice 裡配置:
伺服器端驗證通過後,會頒發訪問令牌和重新整理令牌,如下圖 access_token 和 refresh_token 欄位所示:
SAP Commerce Cloud UI 在 OAuth 體系中扮演的角色是客戶端,通過訪問令牌,獲得訪問 Commerce 後臺伺服器上的業務資料的許可。而重新整理令牌,用於當訪問令牌過期時,由客戶端憑藉其換取新的訪問令牌。重新整理令牌本身是一個憑證,表明持有其的客戶端,曾經通過 OAuth 認證,獲得了訪問受保護資源的許可,當通過重新整理令牌再次請求新的訪問令牌時,客戶端不用再從頭開始走一遍 OAuth 認證的完整流程。
SAP Commerce Cloud 的訪問令牌和重新整理令牌都有過期時間,有時也稱為 TTL(Time-to-Live,存活時間),預設值分別為12小時和30天。
而我們團隊的開發人員,在開發 SAP Commerce Cloud UI 使用者會話管理功能,進行各種邊界條件的測試時,為了方便起見,通常將自己本地搭建的 Commerce 伺服器上令牌的過期時間進行了調整。比如下圖的例子,二者分別調整為30秒和60秒之後過期:
訪問令牌獲取之後,在接下來 Commerce Cloud UI 消費後臺 OCC API 時,會將其附加在 HTTP 請求的頭部欄位裡:
如果此時訪問令牌已經過期,則該請求會收到伺服器 401 錯誤的應答:
以及錯誤詳情 InvalidTokenError:Access token expired: IqQ-8cYzHV1gjQOpnYytHTFPt30
顯然這種偏技術的錯誤訊息不應該顯示給使用者,幸運的是我們還有重新整理令牌。此時,SAP Commerce Cloud UI 會將過期的訪問令牌,連同重新整理令牌一齊發送給 Commerce 後臺,申請一個新的訪問令牌:
SAP Commerce Cloud UI 初次登入申請令牌時,grant_type 的值為 password;而訪問令牌過期,使用重新整理令牌重新申請時,grant_type 的值應該填充為 refresh_token.
如果重新整理令牌的過期時間也到達了,該怎麼辦?沒有重新整理令牌,也就無從獲取新的訪問令牌。因此,我們會將使用者重定向到登入頁面,顯示一條“Session expired”的提示資訊,讓其登入之後,重新獲取訪問令牌和重新整理令牌。
前文從淘寶首頁登入說起曾經提到,我們在淘寶網上購物,如果不小心重新整理了瀏覽器,只要客戶端儲存的 Cookie 尚未過期,就可仍然保持登入狀態。這樣,客戶重新整理之前的會話,比如新增商品到購物車,或者正在進行結帳的某一步,仍然處於有效狀態。
SAP Commerce Cloud UI 通過將訪問令牌持久化到瀏覽器的 Local Storage 中來實現上述場景。
每當使用者成功登入後,我們將 Commerce 後臺伺服器頒發的訪問令牌進行持久化儲存,儲存到瀏覽器 Local Storage 中。
每次 SAP Commerce Cloud UI 初始化時,通過 Angular APP_INITIALIZER 這個注入令牌,我們開發了 AuthStatePersistenceService 服務,將瀏覽器本地儲存中的令牌同步到記憶體中。
採取這種設計後,即使使用者在購物過程中重新整理了瀏覽器,SAP Commerce Cloud UI 重新載入後,從 Local Storage 中取出訪問令牌同步到記憶體中,接下來的使用者操作,繼續使用該令牌呼叫 Commerce OCC API,不會因瀏覽器重新整理而中斷。
總結起來,SAP Commerce Cloud UI 有關訪問令牌和重新整理令牌的使用場景如下:
(1) 使用者登入後,SAP Commerce Cloud UI 將伺服器頒發的訪問令牌儲存於記憶體中,並持久化到瀏覽器 Local Storage.
對於重新整理令牌,出於安全性考慮,我們團隊實現時,僅將其維護在應用記憶體中,並不進行持久化操作。
(2) 當用戶操作 UI,觸發 API 呼叫後收到伺服器返回的訪問令牌過期的錯誤之後,SAP Commerce Cloud UI 自動利用重新整理令牌,申請新的訪問令牌;待拿到新的訪問令牌之後,使用該令牌重新呼叫之前因為舊的訪問令牌過期而失敗的 API;這一系列機制對於使用者來說完全透明,使用者在介面上的操作不會受到任何影響。
(3) 如果使用者操作觸發的 API 呼叫收到的伺服器返回為重新整理令牌過期,SAP Commerce Cloud UI 會暫存當前使用者瀏覽頁面的 URL,並將使用者重定向到登入頁面;使用者重新登入後,獲取到新的訪問令牌和重新整理令牌,再被 SAP Commerce Cloud 重定向到重新整理令牌過期時正在操作的頁面。
本文簡單介紹了 SAP Commerce Cloud UI 使用者會話管理的基本實現原理和支援的場景。對其技術實現感興趣的朋友,可以查閱我們團隊釋出在 Github 上的文件,感謝閱讀。
https://sap.github.io/spartacus-docs/session-management
更多閱讀
更多Jerry的原創文章,盡在:"汪子熙":