Skip to content
AI 文档索引 ↗

B2B 组织属性与服务端租户边界 ​

本文区分两种用途不同的上下文:客户端 groupId 用于记录用户当前所属的分析组织;服务端 tenantId 可用于表达由宿主认证状态确定的租户上下文。客户端传入的业务属性不能充当服务端鉴权或数据隔离依据。

1. 当前 SDK 能力 ​

字段/操作当前支持范围边界
userId / identify()Web、iOS、Android 客户端由宿主提供;变更为另一用户时使用 switchUser(),不要静默覆盖身份
groupId客户端 SDK 的 group(groupId, traits);服务端 SDK 可在 ServerIdentity 显式提供分析组织上下文;客户端 traits 写入 $group 事件,不作为后续事件的公共属性
tenantId协议模型及 Node.js、Java、Go、Python 服务端 SDK 的 ServerIdentity由服务端宿主从可信认证/业务上下文提供;当前客户端 SDK 没有设置租户 ID 的公开 API

客户端使用 group() 记录分析组织;服务端使用 ServerIdentity.tenantId 记录可信租户上下文。租户认证与数据隔离由业务后端负责。

2. 客户端组织分析 ​

客户端可以在宿主确认用户所属组织后调用 group()。切换组织只影响后续事件的 groupId 快照;已经创建并排队的事件保持原快照。groupTraits 随 $group 系统事件发送,不会自动附加到每条业务事件。

ts
await analytics.identify('user-123');
await analytics.group('org-456', { plan: 'enterprise' });
analytics.track('report_exported', { format: 'csv' });

org-456 和 plan 是宿主提供的分析上下文。若把组织 ID 放进普通事件属性,它仍只是普通业务数据;SDK 不会据此校验用户是否有权访问该组织。

账号切换沿用身份生命周期合同:换人时使用 switchUser();仅切换分析组织时使用 group()。退出或清理行为按 统一身份与生命周期核心概念 执行。SDK 不推断组织,也不把组织切换解释为登录或授权操作。

3. 服务端权威租户上下文 ​

服务端 SDK 可在创建 ServerIdentity 时提供 tenantId。宿主必须从已认证的服务端请求/业务状态中取得该值,而不是信任任意客户端请求头或事件属性。示例(Java):

java
ServerIdentity identity = ServerIdentity.builder()
    .userId(authenticatedUser.id())
    .tenantId(authenticatedUser.tenantId())
    .build();
client.track(TrackRequest.builder("report_exported", identity).build());

Node.js、Go、Python 的服务端身份模型也接受显式 tenantId。这些 SDK 负责将宿主提供的身份快照编码到事件;认证、授权、租户归属校验和数据隔离由服务端负责。请在目标 Collector 和数据平台验证隔离策略。

订单、订阅变更、支付和退款等权威事实应由完成认证并确认业务结果的服务端产生。客户端可记录浏览、加购、点击等行为;这些行为不能证明支付或授权结果。金额字段与事件名称使用客户自己的业务合同,参考行业场景事件建模示例。

4. Web 项目与存储隔离 ​

同源页面运行不同 SDK 项目时,应为各自配置正确的 endpoint 和 projectKey。Web SDK 按项目作用域隔离本地状态;storageNamespace 仅用于同一项目下的可选本地命名空间,不能表示租户身份,也不能代替服务端授权。不要把邮箱、手机号或 Token 放入命名空间。

5. 验收范围 ​

验证项本地可验证需要对应部署系统验证
group() 更新后续事件上下文,旧事件快照不变客户端单测/Host 测试—
服务端 ServerIdentity.tenantId 序列化到事件四语言服务端 SDK 测试Collector 是否据此隔离数据
tenantId 来源可信—服务端认证、授权和租户归属检查
Kafka/数据库/分析仓库中的租户隔离—对应数据平台部署与权限测试
Web 不同项目的本地状态隔离浏览器多项目测试实际生产项目凭据与环境配置

租户隔离需要在目标 Collector、数据库及数仓中分别验证。