Skip to content
AI 文档索引 ↗

服务端身份与多租户 ​

用户流程可能横跨 Web、移动应用和服务端。本文介绍登录时的匿名身份关联、服务端事件的客户端 Session 归属和 B2B 租户上下文。SDK 不负责用户认证,身份合并能力需由实际部署的数据平台提供。


一、 跨端身份关联 ​

1. 注册/登录:显式身份关联 ​

在注册/登录成功的业务节点,宿主从自己的认证结果取得 userId;若用户已允许分析采集,再从 Web SDK 的 getIdentitySnapshot()?.anonymousId 或原生 SDK 的公开快照取得匿名 ID,随该次业务请求显式传给业务后端。后端检查来源、Consent 策略、字段格式和账号切换边界后,调用服务端 SDK 的注册关联方法,例如 Java 的 trackSignup(userId, anonymousId) 或 Go 的 TrackSignup。普通已登录服务端事件只需从认证会话显式提供 userId,无需在每个 API 请求上传匿名 ID。

trackSignup 生成 $identity_login 服务端事件。Collector 的整批 ACK 只确认批次接收;需要关联登录前后行为时,还应验证实际数据平台的身份合并与查询结果。

2. 服务端事件归属客户端 Session:可选单字段 ​

当支付等服务端事件确实属于当前客户端分析 Session 时,宿主可在该次业务请求上显式附带 X-Track-Session-ID。Web 的 createWebRequestContextHeaders(client, requestUrl, { allowedOrigins }) 仅在 Consent 已授权、目标精确 Origin 被允许时生成这一个 Header;它不拦截全局 fetch/XHR。该值只能作为事件创建时的非权威 context.client.sessionId;宿主认证得到的 userId 仍须作为每事件 ServerIdentity 显式传入。缺失或畸形 Session ID 不应阻断业务请求。

服务端 SDK 下载包不包含 Java Servlet 和 Go Gin 适配器。Java 和 Go 宿主可以使用 Core API 显式传递上下文。

注册关联与 Session 归属是两个独立入口:X-Track-Session-ID 不能触发 trackSignup,登录时的 anonymousId 也不必随所有业务请求进入分析 Header。自定义 Header 跨源时,业务 API 还需配置 CORS 预检与代理转发策略。


二、 多命名空间身份绑定 (identityBindings) ​

在复杂生态(如微信小程序、企业微信、支付宝小程序、三方联盟登录)中,同一个真实用户在不同渠道拥有不同的外部凭证标识。

服务端 SDK 支持通过 identityBindings 随事件提交有命名空间的业务标识。它只负责按事件快照传输这些标识;下游是否支持身份解析、账号关联或查询合并,取决于部署方的数据处理能力。不要将凭据、原始个人信息或 Provider 候选信号放入绑定字段;对个人标识做哈希并不会自动使其匿名化。

java
// Java 示例:多命名空间绑定
Map<String, String> bindings = new HashMap<>();
bindings.put("wechat_unionid", "oUpF8uMuAJO_M2pxb1Q9z8");
bindings.put("partner_account", "partner-user-42");

ServerIdentity identity = ServerIdentity.builder()
    .userId("user_1024")
    .anonymousId("anon_uuid_999")
    .identityBindings(bindings)
    .build();

client.track("account_linked", identity, properties);

三、 B2B 租户与组织上下文 ​

B2B SaaS 分析可按用户、企业租户(Tenant)或组织/工作区(Group/Organization)查看事件。

1. 租户模型定义 ​

  • tenantId:宿主认证后的企业租户标识,供接收端使用其租户策略处理;
  • groupId:分析组织标识,如部门、项目组或工作空间。SDK 不执行租户授权或数据隔离。

2. 记录多租户事件 ​

java
ServerIdentity identity = ServerIdentity.builder()
    .userId("employee_888")
    .tenantId("tenant_acme_corp")
    .groupId("workspace_marketing")
    .build();

Map<String, Object> properties = new HashMap<>();
properties.put("export_format", "pdf");
properties.put("page_count", 35);
client.track("document_exported", identity, properties);

注意:tenantId 与 groupId 表示组织/租户上下文,不能替代主体身份;每次事件仍必须至少包含一个主体标识。identityBindings 最多包含 10 项;命名空间以英文字母开头,可使用字母、数字、.、_、:、-,最长 64 个字符;值须包含非空白字符,最多 512 个 Unicode 码点。


四、 服务端身份约束 ​

  • 服务端进程会并发处理多个用户请求,SDK 不维护全局“当前用户”。宿主完成认证后,应为每条事件显式传入该请求的身份;不要在共享 Client 上固化单个 userId。
  • profileDelete 发送 $profile_delete 操作,不代表删除历史事件、备份或身份关系。主体数据删除需由部署方提供的合规流程处理。