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 UI 的用户会话管理

关于 SAP Commerce Cloud Headless 架构的更多介绍,请参考我之前的文章:Jerry在2020 SAP全球技术大会的分享:SAP Spartacus技术介绍的文字版

SAP Commerce Cloud UI 的用户会话管理

SAP Commerce Cloud 有个名为 Oauth2 的 extension,基于 OAuth 2.0 协议实现了用户认证和令牌颁发/功能,支持 OAuth 2.0 协议定义的包括 Resource Owner Password Flow 在内的全部四种认证流。

SAP Commerce Cloud UI 的用户会话管理

SAP Commerce Cloud UI 扮演了 OAuth 2.0 认证框架中的客户端 (Client) 角色,通过消费 SAP Commerce Oauth2 扩展提供的 OAuth 系列 API,实现用户会话管理。

让我们从最初始的用户登录场景说起。

输入用户名和密码:

SAP Commerce Cloud UI 的用户会话管理

SAP Commerce Cloud UI 调用 Commerce OAuth2 API,endpoint 为 /authorizationserver/oauth/token, 将用户名,密码,client_id 和 client_secret 去换取访问令牌(Access Token)和刷新令牌(Refresh Token).

SAP Commerce Cloud UI 的用户会话管理

这里的 SAP Commerce Cloud UI 作为 OAuth 认证体系里的客户端,其 client_id 和 client_secret 在 Commerce Backoffice 里配置:

SAP Commerce Cloud UI 的用户会话管理

服务器端验证通过后,会颁发访问令牌和刷新令牌,如下图 access_token 和 refresh_token 字段所示:

SAP Commerce Cloud UI 的用户会话管理

SAP Commerce Cloud UI 在 OAuth 体系中扮演的角色是客户端,通过访问令牌,获得访问 Commerce 后台服务器上的业务数据的许可。而刷新令牌,用于当访问令牌过期时,由客户端凭借其换取新的访问令牌。刷新令牌本身是一个凭证,表明持有其的客户端,曾经通过 OAuth 认证,获得了访问受保护资源的许可,当通过刷新令牌再次请求新的访问令牌时,客户端不用再从头开始走一遍 OAuth 认证的完整流程。

SAP Commerce Cloud 的访问令牌和刷新令牌都有过期时间,有时也称为 TTL(Time-to-Live,存活时间),默认值分别为12小时和30天。

SAP Commerce Cloud UI 的用户会话管理

而我们团队的开发人员,在开发 SAP Commerce Cloud UI 用户会话管理功能,进行各种边界条件的测试时,为了方便起见,通常将自己本地搭建的 Commerce 服务器上令牌的过期时间进行了调整。比如下图的例子,二者分别调整为30秒和60秒之后过期:

SAP Commerce Cloud UI 的用户会话管理

访问令牌获取之后,在接下来 Commerce Cloud UI 消费后台 OCC API 时,会将其附加在 HTTP 请求的头部字段里:

SAP Commerce Cloud UI 的用户会话管理

如果此时访问令牌已经过期,则该请求会收到服务器 401 错误的应答:

SAP Commerce Cloud UI 的用户会话管理

以及错误详情 InvalidTokenError:Access token expired: IqQ-8cYzHV1gjQOpnYytHTFPt30

SAP Commerce Cloud UI 的用户会话管理

显然这种偏技术的错误消息不应该显示给用户,幸运的是我们还有刷新令牌。此时,SAP Commerce Cloud UI 会将过期的访问令牌,连同刷新令牌一齐发送给 Commerce 后台,申请一个新的访问令牌:

SAP Commerce Cloud UI 的用户会话管理

SAP Commerce Cloud UI 初次登录申请令牌时,grant_type 的值为 password;而访问令牌过期,使用刷新令牌重新申请时,grant_type 的值应该填充为 refresh_token.

如果刷新令牌的过期时间也到达了,该怎么办?没有刷新令牌,也就无从获取新的访问令牌。因此,我们会将用户重定向到登录页面,显示一条“Session expired”的提示信息,让其登录之后,重新获取访问令牌和刷新令牌。

SAP Commerce Cloud UI 的用户会话管理

前文从淘宝首页登录说起曾经提到,我们在淘宝网上购物,如果不小心刷新了浏览器,只要客户端存储的 Cookie 尚未过期,就可仍然保持登录状态。这样,客户刷新之前的会话,比如添加商品到购物车,或者正在进行结帐的某一步,仍然处于有效状态。

SAP Commerce Cloud UI 通过将访问令牌持久化到浏览器的 Local Storage 中来实现上述场景。

每当用户成功登录后,我们将 Commerce 后台服务器颁发的访问令牌进行持久化存储,保存到浏览器 Local Storage 中。

SAP Commerce Cloud UI 的用户会话管理

每次 SAP Commerce Cloud UI 初始化时,通过 Angular APP_INITIALIZER 这个注入令牌,我们开发了 AuthStatePersistenceService 服务,将浏览器本地存储中的令牌同步到内存中。

SAP Commerce Cloud UI 的用户会话管理

SAP Commerce Cloud UI 的用户会话管理

采取这种设计后,即使用户在购物过程中刷新了浏览器,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 的用户会话管理

本文简单介绍了 SAP Commerce Cloud UI 用户会话管理的基本实现原理和支持的场景。对其技术实现感兴趣的朋友,可以查阅我们团队发布在 Github 上的文档,感谢阅读。

https://sap.github.io/spartacus-docs/session-management

SAP Commerce Cloud UI 的用户会话管理

更多阅读

更多Jerry的原创文章,尽在:"汪子熙":
SAP Commerce Cloud UI 的用户会话管理

上一篇:【PyTorch】zergtant/pytorch-handbook——4.2.3-cnn-visualizing


下一篇:SAP Commerce Cloud 项目 Spartacus 入门