多租户集成与单点登录

前言

多租户是云应用的常见模式。不同组织共用单个实例,通常可降低维护成本并提高效率。

Editor 组件用于创建和管理座位图的可视化表示。本指南适用于票务平台提供多租户能力,且集成模型需要支持这一场景的情况。

目标

主要目标是在两个平台之间无缝支持多租户模型。 允许为不同组织建立独立工作空间。为实现此目标,需要在两个平台之间实现 SSO。

在票务软件中,租户可能对应组织或客户。

集成

定义

下文使用以下术语:

  • Ticketing Platform(TP):需要集成的票务平台。
  • Seatmap.pro(SMP):由两个主要组件组成的平台:
    • Editor:座位图编辑界面应用。
    • Booking:处理身份验证和组织管理的平台 API 组件。

模型

将用户关联到特定租户,划定访问范围,以隔离两个或多个组织之间的访问。

多租户用户模型

一个租户或组织通常可以包含多个用户。

主流程

考虑已在 TP 登录的用户尝试打开 SMP Editor 的场景。为跳过 SMP 端的登录步骤,用户需要身份验证凭据。连接两个平台的步骤如下:

  1. TP 识别当前用户的组织,检查它是否已在 SMP Booking 端存在并拥有 ID,以同步组织。
    • 如果组织尚不存在,TP 应先通过组织管理 API 创建。
  2. 确定组织 ID 后,TP 使用 autoLogin 方法请求一次性会话代码。
  3. TP 使用 autoLogin 返回的代码打开 SMP Editor;Editor 加载时将代码兑换为会话。旧版集成也可直接获取并传入 token 和 refreshToken。

单点登录时序

创建组织

以编程方式创建组织,需要调用 SMP Booking 端的管理 API:

POST /api/private/management/v2.0/organizations/ HTTP/1.1
Host: {BOOKING_HOST}
Content-Type: application/json
X-API-Key: {tenantToken}

{
    "name": "Organization Name",
    "email": "jd@seatmap.pro",
    "firstName": "John",
    "lastName": "Doe",
    "password": "{INITIAL_PASSWORD}",
    "autologinEnabled": true
}

此端点要求在 X-API-Key 请求头中发送租户令牌,组织令牌会被拒绝。响应包含新建组织及其 ID,后续操作需要使用该 ID。将 autologinEnabled 设为 true,允许组织接受下文的自动登录请求;省略时默认为 false。

组织名称和管理员详情位于同一个对象的顶层字段。email 标识组织管理员账户,匹配时不区分大小写。若邮箱尚未被使用,则以提供的密码创建账户。已有账户只有同时满足以下条件才会成为管理员:该邮箱仅对应一个账户;账户至少属于一个组织;其所属的所有组织均归 X-API-Key 对应的租户所有;且账户不具有平台管理角色(租户管理员或全局管理员)。该账户保留原密码,传入的 password 不生效。其他已有账户会导致请求返回 409 Conflict 和错误代码 ACCOUNT_EMAIL_IN_USE,且不创建任何内容;请为该组织使用其他邮箱。

自动登录请求

自动登录方法用于获取用户会话,由 SMP Booking 系统处理:

POST /api/public/v2.0/autologin/ HTTP/1.1
Host: {BOOKING_HOST}
Content-Type: application/json
Content-Length: 164

{
    "login": "jd@seatmap.pro",
    "firstName": "John",
    "lastName": "Doe",
    "token": "{PRIVATE_KEY}",
    "responseType": "code"
}

设置 "responseType": "code"(推荐)时,响应返回一次性会话代码,而不是会话令牌。代码只能兑换一次,60 秒后过期:

{
  "success": true,
  "code": "{ONE_TIME_CODE}",
  "expiresIn": 60
}

省略 responseType 时,响应直接包含会话令牌:

{
  "user": {
    // User information
  },
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

自动登录仅接受组织账户。具有平台管理角色(租户管理员或全局管理员)的账户会收到 HTTP 403,必须使用自己的密码登录 Editor。

打开 Editor 应用

将会话代码作为 ssoCode URL 参数,在 iframe 中打开 SMP Editor。Editor 加载后自动将代码兑换为会话:

<iframe
  src="{EDITOR_HOST}/app/?ssoCode={ONE_TIME_CODE}"
  width="100%"
  height="800px"
  frameborder="0"
>
</iframe>

每次打开 Editor 都应向自动登录端点请求新代码;代码在首次加载时消耗,无法重复使用。

如果使用默认的令牌响应,则改为将 token 和 refreshToken 加到 URL 参数中:

<iframe
  src="{EDITOR_HOST}/app/?token={token}&refreshToken={refreshToken}"
  width="100%"
  height="800px"
  frameborder="0"
>
</iframe>
示例

假设要打开 https://editor.seatmap.dev/app/venues/2/schemas/150 对应的场地座位图,自动登录响应返回代码 k3P9wXbF2tR8yQ6mA1sD4gJ7hL0cV5nZ8xE2uT6iO4q。

iframe 使用的完整 URL 为:

https://editor.seatmap.dev/app/venues/2/schemas/150?ssoCode=k3P9wXbF2tR8yQ6mA1sD4gJ7hL0cV5nZ8xE2uT6iO4q

完整 iframe 实现如下:

<iframe
  src="https://editor.seatmap.dev/app/venues/2/schemas/150?ssoCode=k3P9wXbF2tR8yQ6mA1sD4gJ7hL0cV5nZ8xE2uT6iO4q"
  width="100%"
  height="800px"
  frameborder="0"
>
</iframe>

输入功能、设置、端点或 SDK 方法。