Skip to content

用户管理服务接入方案 ​

本文只描述方案,不展开代码实现。推荐采用“接口接入”的方式:用户管理服务继续作为用户主数据来源,flow-talk-server 只通过 HTTP 接口校验登录态、读取用户资料,并签发 IM 自己的 token。

目标 ​

  • 用户账号、密码、组织、禁用状态由用户管理服务维护。
  • IM 服务不保存外部 access token,不直接管理外部账号密码。
  • IM 服务内部仍使用 users.id 关联会话、消息、群成员、设备和在线状态。
  • 前端登录后通过接口换取 IM token,后续 IM HTTP 和 WebSocket 都使用 IM token。

推荐架构 ​

text
前端
  -> 用户管理服务登录接口
  -> 获得用户管理服务 access_token
  -> flow-talk-server /api/auth/external
  -> flow-talk-server 调用户管理服务校验接口
  -> flow-talk-server 同步内部 users
  -> flow-talk-server 返回 IM JWT
  -> 前端使用 IM JWT 调 IM 接口和 WebSocket

核心边界:

  • 前端不能把用户资料直接传给 IM 服务并让 IM 信任。
  • IM 服务必须通过用户管理服务接口校验 access_token。
  • IM 服务只信任用户管理服务返回的用户 ID、昵称、头像和状态。
  • 后续 IM 权限判断只依赖内部 users.id。

接口清单 ​

1. 用户管理服务:登录接口 ​

由用户管理服务提供,前端调用。

text
POST /api/auth/login

请求示例:

json
{
  "username": "zhangsan",
  "password": "******"
}

响应示例:

json
{
  "access_token": "user-center-access-token",
  "expires_in": 7200
}

说明:

  • 该接口不由 flow-talk-server 实现。
  • IM 前端可以复用现有用户管理系统登录页,也可以由用户管理系统跳转回来。

2. 用户管理服务:Token 校验和用户资料接口 ​

由用户管理服务提供,flow-talk-server 调用。

text
GET /api/users/me
Authorization: Bearer <user-center-access-token>

成功响应:

json
{
  "id": "10001",
  "username": "zhangsan",
  "nickname": "张三",
  "avatar_url": "https://example.com/avatar.png",
  "status": "enabled"
}

失败响应建议:

场景HTTP
token 缺失401
token 无效或过期401
用户被禁用403
用户不存在404
用户管理服务异常5xx

3. IM 服务:外部登录换取 IM Token ​

由 flow-talk-server 提供,前端调用。

text
POST /api/auth/external
Content-Type: application/json

请求示例:

json
{
  "provider": "user-center",
  "access_token": "user-center-access-token"
}

成功响应:

json
{
  "code": 200,
  "data": {
    "user": {
      "id": 1,
      "external_id": "user-center:10001",
      "username": "zhangsan",
      "nickname": "张三",
      "avatar_url": "https://example.com/avatar.png",
      "auth_source": "external",
      "status": 1
    },
    "token": "flow-talk-jwt"
  },
  "message": "登录成功"
}

说明:

  • provider 是服务端白名单,例如 user-center。
  • access_token 是用户管理服务签发的 token。
  • 返回的 token 是 IM 服务自己的 JWT。
  • 后续 IM 请求不能继续使用用户管理服务 token。

时序流程 ​

text
1. 前端调用用户管理服务登录接口
2. 用户管理服务返回 access_token
3. 前端调用 flow-talk-server POST /api/auth/external
4. flow-talk-server 根据 provider 找到用户管理服务配置
5. flow-talk-server 调用户管理服务 GET /api/users/me
6. 用户管理服务返回当前用户资料和状态
7. flow-talk-server 按 external_id 查找或创建内部 users
8. flow-talk-server 签发 IM JWT
9. 前端保存 IM JWT
10. 前端使用 IM JWT 调用会话、消息、设备、WebSocket 等接口

字段映射 ​

用户管理服务字段IM 用户字段说明
idexternal_id建议加 provider 前缀,例如 user-center:10001
usernameusername用于账号展示和唯一约束
nicknamenickname用于聊天展示
avatar_urlavatar_url用于头像展示
statusstatusenabled 映射为 1,禁用映射为 0 或直接拒绝登录

external_id 必须稳定,不建议使用手机号、邮箱、昵称等可变字段。

内部用户同步策略 ​

IM 服务收到用户管理服务资料后,按以下策略处理:

  1. 使用 external_id = provider + ":" + user_center_id 查询 users。
  2. 如果存在,刷新昵称、头像和启用状态。
  3. 如果不存在,创建一条 auth_source = external 的内部用户。
  4. 返回内部用户并签发 IM JWT。

不要在同步时改动:

  • 内部 users.id
  • 历史消息 sender_id
  • 会话成员 conversation_members.user_id

原因:IM 历史数据必须长期绑定内部用户 ID。

鉴权边界 ​

前端需要保存两个不同 token 的语义:

Token来源用途
用户管理服务 access_token用户管理服务只用于调用 /api/auth/external
IM JWTflow-talk-server用于所有 IM HTTP 接口和 WebSocket

IM HTTP 请求:

text
Authorization: Bearer <flow-talk-jwt>

IM WebSocket:

text
ws://127.0.0.1:8080/api/ws?token=<flow-talk-jwt>&device_id=<device_id>

错误处理建议 ​

flow-talk-server 对外建议保持稳定错误语义:

用户管理服务返回IM 对前端返回
401 token 无效401 或 400,提示重新登录
403 用户禁用403,提示用户已禁用
404 用户不存在401 或 400,提示登录态无效
5xx 服务异常502 或 503,提示用户服务暂不可用
超时504 或 503,提示稍后重试

当前项目已有基础错误映射,真实接入时建议把用户管理服务异常和 token 无效区分开,方便前端展示不同提示。

安全要求 ​

  • IM 服务不得信任前端传入的用户 ID、昵称、头像。
  • IM 服务不得把用户管理服务 access_token 写入数据库。
  • 日志中不得打印完整 access_token 或 IM JWT。
  • provider 必须是服务端白名单。
  • 用户管理服务接口建议使用 HTTPS 或内网可信链路。
  • IM 服务调用用户管理服务必须设置超时时间。
  • 用户被禁用时不能换取新的 IM JWT。

最小联调 ​

当前项目已有 demo provider,可以先用它验证外部登录链路:

bash
curl -X POST http://127.0.0.1:8080/api/auth/external \
  -H "Content-Type: application/json" \
  -d '{"provider":"demo","access_token":"external-user-001"}'

预期:

  • 返回 IM JWT
  • 返回 user.auth_source = external
  • users.external_id = demo:external-user-001

真实用户管理服务接入时,把 provider 从 demo 换成 user-center,并让 IM 服务通过接口调用用户管理服务校验 token。

落地清单 ​

基于 MIT 许可发布