登录体系统一整合方案
日期:2026-06-29 | 基于《统一认证服务(UAS)概要设计 v3》及 VTS 消息推送需求
1. 现状梳理与问题定义
1.1 涉及系统与组件总览
| 系统/组件 | 认证方式 | 身份标识 | openID/unionid 存储位置 |
|---|---|---|---|
| 微信小程序(多个) | wx.login -> UAS (grant_type=mp_code) -> access_token | pptid(通行证ID) | UCOUT(通过 retrieveOpenInfo 获取,绑定关系存通行证) |
| 微信公众号 — 卓越会员微服务 | OAuth2 网页授权 | openID | 微信代理(wxprx)记录 openID |
| 城市服务号(多个,按城市申请) | OAuth2 网页授权 | openID(各服务号独立) | 微信代理 / 教学服务单独保存 openID 与 memberID 关系 |
| H5/Web 业务系统(网报等) | SSO(CAS 4.2.6,Cookies/Session) | system_id + 业务用户ID | 不直接存储 openID |
| UAS 统一认证服务 | OAuth2/OIDC Token-Based | pptid + access_token | 通过 UCOUT 查询微信绑定 |
| UCOUT 用户中心 | 内部接口服务 | pptid | 存储通行证与微信绑定关系 |
| 会员库 | 内部数据服务 | 家长 memberid / 学员 memberid | 不存储 openID |
| VTS 消息推送服务 | 内部服务调用 | 城市+服务号 appid + openID | VTS 自身维护城市+服务号关系,openID 依赖外部 |
| 微信代理(wxprx) | 微信 API 代理 | openID | 记录 openID 解密结果 |
| TMS/evip | 业务系统,各自认证 | 学员编号(与会员库 memberid 1:1) | 不存储 openID |
1.2 各端登录流程现状
1.3 核心问题分析
问题一:openID/unionid 分散
现状:
- 每个微信小程序和公众号各自持有独立的 openID
- unionid 需要所有应用绑定到同一微信开放平台账号才能获取
- 当前 openID 存储分散:通行证存一部分、微信代理存一部分、教学服务存一部分
- 语雀文档明确指出:"openid 不在通行证关联,因为全日制或者有些业务不用通行证"
断裂点:
- 城市服务号与通行证之间没有直接关联,openID 存于教学服务
- 全日制业务不使用通行证,其用户的 openID 与通行证体系完全脱节
- 不同公众号的 openID 无法直接互通,依赖 unionid 桥接但覆盖不全
问题二:多端登录不互通
现状:
- 小程序走 UAS(Token-Based)
- H5/Web 走 SSO(CAS Cookies/Session)
- 公众号 H5 走微信 OAuth2,业务系统自行处理身份
- UAS 与 SSO 之间仅有单向桥接(小程序 -> H5),缺少反向桥接
断裂点:
- 公众号 H5 场景下获取的 openID 无法与 UAS 通行证身份关联
- SSO 登录后无法获取 UAS Token,Web 端与小程序端身份不互通
- 各业务系统(网报、TMS/evip)接入认证方式不统一
问题三:消息推送与身份脱节
现状:
- VTS 按城市服务号推送模板消息,需要知道用户在目标服务号下的 openID
- openID 来源分散:通行证、微信代理、教学服务各自存储
- VTS 无法统一查询"某用户在某服务号下的 openID"
断裂点:
- 用户更换城市后,新城市服务号的 openID 可能未被记录
- 会员库 memberid 与服务号 openID 之间缺少统一映射
- "不关注公众号也可获取 openID"的场景下,openID 的存储与查询链路不清晰
2. openID/unionid 统一管理方案
2.1 核心原则
- unionid 作为微信生态层的统一用户标识:所有公众号、小程序必须绑定到同一微信开放平台账号,确保 unionid 可获取
- openID 映射集中管理:建立统一的 openID 映射表,收口各渠道的 openID 数据
- 兼容非通行证用户:全日制等不使用通行证的业务,通过会员 memberid 关联,不强制绑定通行证
2.2 微信开放平台绑定要求
| 应用类型 | 绑定要求 | 当前状态(需确认) |
|---|---|---|
| 微信小程序 A | 绑定开放平台,可获取 unionid | 待确认 |
| 微信小程序 B | 绑定开放平台,可获取 unionid | 待确认 |
| 卓越会员微服务(公众号) | 绑定开放平台,可获取 unionid | 待确认 |
| 城市服务号 1 | 绑定开放平台,可获取 unionid | 待确认 |
| 城市服务号 2 | 绑定开放平台,可获取 unionid | 待确认 |
| 城市服务号 N | 绑定开放平台,可获取 unionid | 待确认 |
前提条件:所有应用必须绑定到同一微信开放平台账号,否则无法获取 unionid,跨应用身份打通将无法实现。
2.3 openID 映射表设计
在 UCOUT 服务中新建统一的微信身份映射表,收口所有 openID 数据:
-- 微信身份映射表(集中管理所有公众号/小程序的 openID)
CREATE TABLE pp_wechat_openid_map (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
unionid VARCHAR(64) NULL COMMENT '微信 unionid(开放平台绑定后可获取)',
openid VARCHAR(64) NOT NULL COMMENT '微信 openid',
wechat_type VARCHAR(32) NOT NULL COMMENT '微信应用类型标识(对应 UCOUT wechat_type)',
app_id VARCHAR(64) NOT NULL COMMENT '微信应用 AppID',
app_category VARCHAR(16) NOT NULL COMMENT '应用类别:miniprogram / mp_service / mp_subscribe',
pptid BIGINT NULL COMMENT '通行证 ID(已绑定时关联)',
member_id BIGINT NULL COMMENT '会员库 memberid(非通行证用户关联)',
bindsource VARCHAR(16) NULL COMMENT '绑定来源:passport / member / teaching',
status TINYINT DEFAULT 1 COMMENT '状态:1-有效 0-无效',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_openid_apptype (openid, wechat_type),
KEY idx_unionid (unionid),
KEY idx_pptid (pptid),
KEY idx_member_id (member_id),
KEY idx_appid (app_id)
) COMMENT '微信 openID 统一映射表';
表设计说明:
unionid可为空:部分场景下(如用户仅在某公众号内授权)可能暂时拿不到 unionidpptid可为空:兼容全日制等不使用通行证的业务,通过member_id关联bindsource标记数据来源:passport(通行证绑定)、member(会员库关联)、teaching(教学服务同步)- 唯一键
(openid, wechat_type)确保同一应用下 openID 不重复
2.4 与 UCOUT 现有接口的关系
当前 UCOUT 提供的微信相关接口:
| 接口 | 用途 | 改造方案 |
|---|---|---|
/getWechatTypeByAppId | 根据 AppId 获取 wechat_type | 无需改造 |
/retrieveOpenInfo | 根据 code + wechat_type 获取 openid/unionid | 改造:获取到 openid/unionid 后,自动写入 pp_wechat_openid_map 表 |
/auth | 通行证账号认证 | 无需改造 |
/wechat/getPhone | 微信手机号解密,完成注册与绑定 | 改造:绑定成功后同步更新 pp_wechat_openid_map 的 pptid |
新增接口:
# 根据 unionid 查询用户在指定公众号下的 openID
POST /ucout/wechat/openid/query
Content-Type: application/json
{
"unionid": "xxx", // 或 member_id
"target_app_id": "xxx" // 目标公众号/小程序的 AppID
}
# 响应
{
"openid": "xxx",
"wechat_type": "xxx",
"bindstatus": "bound" // bound / unbound
}
# 批量同步 openID 数据(用于历史数据迁移)
POST /ucout/wechat/openid/sync
Content-Type: application/json
{
"records": [
{
"openid": "xxx",
"wechat_type": "xxx",
"unionid": "xxx",
"pptid": 123,
"member_id": 456,
"bindsource": "teaching"
}
]
}
2.5 非通行证用户的兼容方案
针对全日制等不使用通行证的业务:
- 通过会员 memberid 关联:openID 映射表中
pptid为空时,使用member_id作为关联键 - 双通道查询:VTS 查询 openID 时,优先通过
unionid查询,其次通过member_id查询 - 渐进式绑定:非通行证用户后续如使用小程序等功能,引导绑定通行证后自动补充
pptid
3. 多端登录互通方案
3.1 目标
所有端(小程序、公众号 H5、Web)的登录认证统一收口到 UAS,各业务系统只需对接 UAS 即可完成身份认证。
3.2 各端登录流程统一设计
3.2.1 小程序登录(保持不变)
3.2.2 公众号 H5 登录(新增 grant_type)
场景:用户在公众号内访问 H5 页面,通过公众号 OAuth2 授权获取身份。
新增 UAS grant_type:mp_oauth(公众号网页授权模式)
接口定义:
# 公众号 H5 网页授权模式获取令牌
POST /uas/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=mp_oauth
&app_id=wxXXX
&login_code=微信OAuth2授权码
&client_id=xxx
&client_secret=xxx
# 成功响应
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 7200,
"scope": "openid profile",
"pptid": 12345,
"openid": "xxx",
"unionid": "xxx"
}
3.2.3 小程序 -> H5 联合认证(保持现有方案)
现有 UAS 联合认证方案(authorize_type=sso_auth)已满足此场景,无需改造:
- 小程序使用已有
access_token请求 UAS 获取uas_sso_code - 携带
uas_sso_code跳转到 H5 页面的 SSO 登录链接 - H5 页面通过 SSO 验证
uas_sso_code完成登录
3.2.4 Web 端 SSO 登录(保持 + 补充 Token 互认)
保持现有 SSO 登录流程不变,补充 SSO -> UAS Token 互认能力:
新增 UAS grant_type:sso_bridge(SSO 桥接模式),让 Web 端业务系统在 SSO 登录后也能获取 UAS Token,实现与小程序端的身份互通。
# SSO 桥接模式获取 UAS Token
POST /uas/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=sso_bridge
&sso_ticket=ST-xxx
&client_id=xxx
&client_secret=xxx
3.2.5 各业务系统统一接入规范
| 接入步骤 | 说明 |
|---|---|
| 1. 注册 UAS 客户端 | 在 UAS 注册 client_id / client_secret,配置回调地址 |
| 2. 选择认证模式 | 小程序用 mp_code,公众号 H5 用 mp_oauth,Web 用 sso_bridge 或保持 SSO |
| 3. 实现登录对接 | 调用 UAS /oauth2/token 获取 access_token |
| 4. 获取用户信息 | 调用 UAS /oauth2/userinfo 获取 pptid、openid 等 |
| 5. 业务令牌颁发 | 基于 UAS 返回的 pptid 颁发业务系统自己的登录态 |
4. 消息推送与身份关联方案
4.1 问题定义
VTS 消息推送的核心链路:
业务系统触发事件 -> VTS 消息服务 -> 确定目标城市+服务号 -> 查找用户在该服务号下的 openID -> 发送模板消息
当前断裂点:VTS 无法可靠地查到"某用户在某城市服务号下的 openID"。
4.2 openID 查询方案
方案:VTS 通过 UCOUT 统一查询 openID
4.3 openID 数据采集策略
针对不同场景,openID 写入映射表的时机和方式:
| 场景 | 采集时机 | 采集方式 | 写入字段 |
|---|---|---|---|
| 小程序登录 | 用户 wx.login 时 | UAS 调用 retrieveOpenInfo 后自动写入 | openid, unionid, wechat_type, app_id |
| 公众号 H5 访问 | 用户 OAuth2 授权时 | UAS mp_oauth 流程中自动写入 | openid, unionid, wechat_type, app_id |
| 通行证绑定 | 手机号授权绑定时 | UCOUT getPhone 回调中更新 pptid | pptid, bindsource=passport |
| 会员库关联 | 会员注册/关联时 | 会员库同步接口 | member_id, bindsource=member |
| 城市服务号首次关注 | 用户关注/进入公众号时 | 微信事件推送 -> 写入映射表 | openid, app_id, app_category=mp_service |
| 历史数据迁移 | 一次性批量导入 | 调用 /ucout/wechat/openid/sync 接口 | 全字段 |
4.4 关键约束处理
约束 1:"不关注公众号也可获取 openID"
微信公众号 OAuth2 网页授权(scope=snsapi_base)可以在用户不关注公众号的情况下获取 openID。因此:
- 用户通过公众号内 H5 页面 OAuth2 授权时,openID 即可写入映射表
- 无需等用户关注公众号,只要用户点击进入公众号菜单/链接触发 OAuth2 即可
约束 2:"用户可在新城市公众号登录绑定"
用户跨城市场景:
- 用户原在城市 A 的服务号有 openID_A
- 用户到城市 B 后,进入城市 B 公众号,OAuth2 授权获取 openID_B
- 通过 unionid 关联,系统识别为同一用户
- openID_B 自动写入映射表,VTS 后续可向城市 B 服务号推送消息
约束 3:"openid 不在通行证关联"
对于全日制等不使用通行证的业务:
- openID 映射表支持
pptid为空,通过member_id关联 - VTS 查询 openID 时支持按
member_id查询 - 业务系统触发消息推送时,传递
member_id而非pptid
4.5 VTS 对接接口
UCOUT 新增查询接口:
# VTS 查询目标 openID
POST /ucout/wechat/openid/resolve
Content-Type: application/json
{
"member_id": 12345, // 会员 memberid(优先)
"unionid": "xxx", // 或 unionid(兜底)
"target_app_id": "wxXXX" // 目标服务号 AppID
}
# 响应
{
"openid": "oXXXX", // 目标服务号下的 openID
"found": true
}
VTS 服务号配置表(VTS 自身维护):
-- VTS 城市与服务号关系(语雀文档中已规划)
CREATE TABLE vts_city_service (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
city_code VARCHAR(16) NOT NULL COMMENT '城市编码',
app_id VARCHAR(64) NOT NULL COMMENT '服务号 AppID',
app_name VARCHAR(128) NULL COMMENT '服务号名称',
status TINYINT DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_city_app (city_code, app_id)
);
-- VTS 服务号与模板关系(语雀文档中已规划)
CREATE TABLE vts_template_config (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
app_id VARCHAR(64) NOT NULL COMMENT '服务号 AppID',
template_id VARCHAR(128) NOT NULL COMMENT '微信模板消息 ID',
msg_type VARCHAR(64) NOT NULL COMMENT '消息类型标识',
status TINYINT DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
5. 整合架构总览
5.1 整合后全链路架构图
mp_code / mp_oauth / sso_bridge / authorization_code] SSO[SSO 认证服务
CAS Cookies/Session] end subgraph 用户数据层 UCOUT[UCOUT 用户中心] OIDMAP[openID 统一映射表
pp_wechat_openid_map] MEMBER[会员库
家长-学员关系] end subgraph 业务系统层 WB[网报系统] TMS[TMS/evip] OTHER[其他业务系统] end subgraph 消息推送层 VTS[VTS 消息服务] end subgraph 代理服务层 WXPRX[微信代理 wxprx] end MP1 -->|wx.login| UAS MP2 -->|wx.login| UAS GZH1 -->|OAuth2| UAS GZH2 -->|OAuth2| UAS GZH3 -->|OAuth2| UAS UAS -->|retrieveOpenInfo| UCOUT UAS -->|写入 openID| OIDMAP UCOUT -->|用户数据| MEMBER SSO <-->|联合认证 uas_sso_code| UAS WB -->|access_token| UAS TMS -->|access_token| UAS OTHER -->|access_token| UAS WB -->|CAS Ticket| SSO VTS -->|查询 openID| OIDMAP VTS -->|城市+服务号配置| VTS VTS -->|模板消息| GZH2 VTS -->|模板消息| GZH3 WXPRX -->|openID 解密| UCOUT MP1 -.->|绑定开放平台| OPEN MP2 -.->|绑定开放平台| OPEN GZH1 -.->|绑定开放平台| OPEN GZH2 -.->|绑定开放平台| OPEN GZH3 -.->|绑定开放平台| OPEN
5.2 核心数据流向
6. 补充说明
6.1 迁移策略
建议分三个阶段推进:
第一阶段:基础设施搭建(1-2 周)
| 步骤 | 内容 | 负责方 |
|---|---|---|
| 1 | 确认所有公众号/小程序是否已绑定同一微信开放平台 | 产品/运营 |
| 2 | 在 UCOUT 中创建 pp_wechat_openid_map 表 | 通行证开发 |
| 3 | 实现 UCOUT openID 查询/同步接口 | 通行证开发 |
| 4 | 历史 openID 数据批量迁移(从微信代理、教学服务同步) | 通行证开发 + 相关系统 |
第二阶段:认证层改造(2-4 周)
| 步骤 | 内容 | 负责方 |
|---|---|---|
| 5 | UAS 新增 mp_oauth grant_type(公众号 H5 场景) | UAS 开发 |
| 6 | UAS 新增 sso_bridge grant_type(SSO 桥接场景) | UAS 开发 |
| 7 | 改造 UAS Token 颁发流程,自动写入 openID 映射表 | UAS 开发 |
| 8 | 公众号 H5 页面对接 UAS mp_oauth 登录 | 前端开发 |
第三阶段:业务系统接入与消息推送(2-4 周)
| 步骤 | 内容 | 负责方 |
|---|---|---|
| 9 | 网报系统接入 UAS 统一认证 | 网报开发 |
| 10 | TMS/evip 接入 UAS 统一认证 | TMS/evip 开发 |
| 11 | VTS 对接 UCOUT openID 查询接口 | VTS 开发 |
| 12 | 各业务系统消息推送对接 VTS | 各业务系统开发 |
| 13 | 端到端联调与测试 | 全员 |
6.2 风险评估
| 风险项 | 风险等级 | 影响 | 应对措施 |
|---|---|---|---|
| 部分应用未绑定微信开放平台 | 高 | 无法获取 unionid,跨应用身份打通失败 | 优先排查并完成绑定,作为第一阶段第一优先级 |
| 历史 openID 数据迁移不完整 | 中 | VTS 找不到部分用户的 openID,消息推送失败 | 分批迁移 + 用户下次访问时自动补充 |
| unionid 覆盖不全(历史用户无 unionid) | 中 | 无法通过 unionid 关联多端身份 | 通过手机号匹配 + 引导用户重新授权 |
| 全日制业务不使用通行证 | 低 | 需要 member_id 双通道关联 | 映射表已设计兼容方案,影响可控 |
| 各业务系统改造进度不一致 | 中 | 部分系统仍使用旧认证方式 | UAS 兼容旧 SSO 流程,渐进式迁移 |
| 城市服务号新增/变更频繁 | 低 | VTS 配置需同步更新 | VTS 提供管理后台,支持动态配置 |
6.3 与 UAS 概要设计文档的关系
| 文档 | 定位 |
|---|---|
| 统一认证服务(UAS)概要设计 v3 | UAS 服务本身的技术设计,聚焦认证协议、接口端点、令牌机制 |
| 本文档(登录体系统一整合方案) | 上层整合方案,聚焦各系统间的身份打通、数据流转、统一接入规范 |
本文档是 UAS 概要设计的上层补充:
- UAS 概要设计定义了"如何认证",本文档定义了"认证后如何打通各系统"
- 本文档提出的
mp_oauth、sso_bridge两个新 grant_type 需要在 UAS 概要设计中补充详细设计 - 本文档提出的 openID 映射表是对 UCOUT 用户数据层的扩展,不影响 UAS 核心架构