统一认证服务(UAS)概要设计

###### 浓缩版 | 基于 v2 (2026-05-11) | 日期:2026-05-26

1. 项目背景与目标

1.1 背景

本项目作为"外部通行证"系统下的一个子服务,负责提供基于 Oauth2 思想的认证服务,提供基于 Token 的认证能力,是原来系统中基于 CAS 架构的认证服务(sso 服务)的补充与完善。

CAS 从 5.x 版本开始原生支持 OIDC Provider 功能,现有 SSO 服务的 CAS 版本为 4.2.6,升级成本较高;同时 CAS 必须依赖于 Cookies/浏览器环境,不适用于小程序、APP 场景。因此选择在不影响原有登录认证流程的基础上,实现新的认证服务。

1.2 目标

  1. 标准化接入:后续所有业务系统(如 SCRM、网报、拼团、转介绍)如需实现无状态的身份认证/单点登录接入通行证体系,均可对接 UAS 进行身份认证。
  2. 功能互补:UAS 除了提供基于 Token 的认证服务外,还提供了与原基于 Cookies/Session 的 CAS 单点登录服务桥接的认证方式,为原有的业务对接新服务提供了更加灵活的身份认证方案。
  3. 全面审计:UAS 会记录所有的身份认证请求,包括但不限于颁发授权码、颁发访问令牌、联合认证等操作,以便后续的审计与数据分析。

1.3 核心定位与业务场景

基于 OAuth2 思想,参照现有 CAS 的业务流程,只负责认证、授权、联合认证验证,不做其余功能与职责。

认证成功后用户端(H5、小程序)需保存 uas 的 access_token。

功能场景列举:

  1. 用户访问小程序 A 正常走微信授权码登录流程。
  2. 用户从小程序 A 跳转访问小程序 B,正常走授权登录流程。
  3. 用户从小程序 A 内部 webview 访问 H5 应用前,通过联合认证流程获取 uas_code 授权码并携带拼接到指定 SSO 登录链接完成登录(兼容原 CAS 登录逻辑)

2. 与现有系统的关系

┌──────────────────────────────────────────────────────────────────┐
│                        外部通行证系统                             │
│                                                                  │
│   ┌──────────────────┐                ┌──────────────────────┐   │
│   │     SSO          │                │     UAS (本项目)      │   │
│   │  Cookies/Session │◄── 联合认证 ──►│  OIDC/OAuth2.0       │   │
│   │  传统 Web 认证    │    (身份互通)   │  Token-Based         │   │
│   └────────┬─────────┘                └──────────┬───────────┘   │
│            │                                     │               │
│            │            ┌──────────────┐         │               │
│            │            │    UCOUT     │         │               │
│            └───────────►│  用户中心     │◄────────┘               │
│                         │  对外服务     │                         │
│                         │  (用户资源)   │                         │
│                         └──────┬───────┘                         │
│                                │                                 │
│            ┌───────────────────┼───────────────────┐             │
│            │                   │                   │             │
│     ┌──────┴──────┐    ┌──────┴──────┐    ┌───────┴──────┐     │
│     │   MySQL     │    │   Redis     │    │ 微信开放平台  │     │
│     │  (共用)     │    │  (共用)     │    │    API       │     │
│     └─────────────┘    └─────────────┘    └──────────────┘     │
└──────────────────────────────────────────────────────────────────┘

系统定位:

系统定位职责
UCOUT用户资源服务用户中心对外服务,提供账号注册/绑定/认证/微信解密等接口,是 SSO 和 UAS 共同依赖的用户数据与业务能力层
SSO传统 Web 认证服务基于 Cookies/Session 的 CAS 单点登录,服务于传统 Web 应用场景
UAS (本项目)无状态认证服务基于 OIDC/OAuth2.0 的 Token 认证服务,服务于小程序、APP 等无状态场景
sso-extendSSO 客户端扩展库提供单点登出能力,UAS 后续可提供类似的客户端 SDK,或复用 sso-extend 的登出机制

SSO 与 UAS 的关系:

UAS 对 UCOUT 的核心依赖接口:

UCOUT 接口用途调用方
/auth通行证账号认证(用户名+密码等)UAS 服务端
/getWechatTypeByAppId根据微信 AppId 获取 wechat\_typeUAS 服务端
/retrieveOpenInfo根据微信 code + wechat\_type 获取 openid/unionidUAS 服务端
/wechat/getPhone微信手机号解密,完成通行证注册与绑定UAS 服务端

***

3. 核心业务流程

3.1 适用于微信小程序的登录认证功能

3.1.1 设计目标

微信小程序无法使用原SSO登录方式,也无法使用标准授权码模式(无浏览器重定向能力),因此 UAS 提供基于微信授权码获取身份令牌的功能。

3.1.2 核心流程:

sequenceDiagram participant 业务小程序 participant 微信服务器 participant UAS participant 业务后端 业务小程序->>微信服务器: wx.login 获取微信 code 微信服务器-->>业务小程序: 返回 code 业务小程序->>UAS: POST /oauth2/token { grant_type=wx_mp_code, wechat_type, wx_code } UAS->>微信服务器: 用 code + wechat_type 换 openid(实际由 ucout 服务和 wxprx 服务完成) 微信服务器-->>UAS: { openid } UAS->>UAS: 查找内部用户绑定(实际由 ucout 服务完成),并生成 access_token UAS-->>业务小程序: { access_token, openid, unionid, pptid } 业务小程序->>业务后端: 携带 access_token 请求业务登录接口 业务后端->>UAS: POST /oauth2/userinfo { access_token } UAS-->>业务后端: { user_info } 业务后端-->>业务小程序: 自行决定如何颁发业务 access_token(可继续使用 access_token,也可以重新包装)

详细步骤:

  1. 小程序调用 wx.login() 获取 wx_login_code,并通过 UCOUT 接口 /getWechatTypeByAppId 查询 wechat_type
  2. 小程序携带 wx_login_code + wechat_type 请求 UAS 授权码端点 POST /oauth2/code/miniprogram
  3. UAS 收到请求后,调用 UCOUT /retrieveOpenInfo 接口,根据 wx_login_code + wechat_type 获取解密后的 openidunionid(可能没有)。
  4. UAS 查询通行证绑定状态:
  1. 小程序携带 uas_login_code 请求业务后端登录接口。
  2. 业务后端向 UAS 标准令牌端点 POST /oauth2/token 发起请求,使用标准授权码模式换取令牌:
  1. UAS 验证 uas_login_code 有效后,颁发 access_token + uas_refresh_token + id_token
  2. 业务后端收到令牌后,自行处理业务登录令牌(如直接使用 access_token 或基于 pptid + uas_refresh_token 生成自己的业务登录令牌)。

未绑定通行证时的补充流程:

sequenceDiagram participant 业务小程序 participant UAS participant 业务后端 participant UCOUT 业务小程序->>UAS: POST /oauth2/code/miniprogram { wx_login_code, wechat_type } UAS-->>业务小程序: { error: "wechat_not_bound", openid, unionid } 业务小程序->>业务小程序: 显示手机号授权按钮,用户点击授权 业务小程序->>UAS: POST /oauth2/code/miniprogram { wx_login_code, wechat_type, wx_phone_code } UAS->>UCOUT: 调用 /wechat/getPhone 完成通行证注册与绑定 UCOUT-->>UAS: { pptid } UAS->>UAS: 生成 uas_login_code UAS-->>业务小程序: { uas_login_code } 业务小程序->>业务后端: 携带 uas_login_code 请求业务接口 业务后端->>UAS: POST /oauth2/token { grant_type=authorization_code, code=uas_login_code } UAS-->>业务后端: { access_token, uas_refresh_token, id_token } 业务后端-->>业务小程序: 业务登录令牌

未绑定通行证详细步骤:

  1. 小程序请求 UAS 授权码端点,UAS 发现微信账号未绑定通行证,返回 wechat_not_bound 错误。
  2. 小程序显示手机号授权按钮,用户点击授权后获取 wx_phone_code
  3. 小程序再次请求 UAS 授权码端点,额外携带 wx_phone_code
  4. UAS 调用 UCOUT /wechat/getPhone 完成通行证注册与绑定,获取 pptid
  5. UAS 生成 uas_login_code 并返回。
  6. 后续步骤与已绑定流程一致。

3.2 SSO认证流程

3.2.1 设计目标

详细流程

3.2.2 安全约束

***

4. 安全约束

安全措施说明
HTTPS 传输所有认证接口强制 HTTPS,确保敏感数据传输安全
授权码模式采用 OAuth2.0 授权码模式(Authorization Code Grant),授权码一次性使用,短时效
非对称密钥签名JWT 采用非对称密钥签名,私钥由 UAS 持有,公钥通过 JWKS 端点分发,业务后端可独立验证令牌合法性
令牌有效期access\_token 合理有效期,refresh\_token 较长有效期(可配置)
客户端密钥机密客户端使用 client_secret 认证,密钥以哈希存储
scope 限制令牌的 scope 严格限制为客户端被授权的 scope,防止越权访问

***

5. 关键数据结构概要

5.1 MySQL

UAS 与 UCOUT 共用 MySQL 实例,UAS 仅用于审计数据记录,不创建与 UCOUT 重复的用户/认证相关表。

5.2 Redis

5.3 会话中 code/token/pptid 的关系

5.3.1 uas_code

/uas/oauth2/authorize端点生成,默认5分钟有效,临时存储于 Reids,一次性使用,使用后删除,不落库

5.3.2 access_token

/uas/oauth2/token端点生成,默认从不过期(暂定),由业务后端(可选)、小程序/前端(保存).

UAS 存储于 Redis,token version 异步落库(pp_acct.token_version),token 中包含 version 信息

暂定用于:①获取联合认证的 code。

5.3.3 uas_refresh_token(未来按需实现)

***

6. 接口端点设计

6.1 标准 OIDC 端点(Spring Authorization Server 内置)

端点方法说明是否启用
/uas/.well-known/openid-configurationGETOIDC 发现端点,返回服务元数据🤔
/uas/oauth2/authorizeGET/POST授权端点,标准授权码模式入口
/uas/oauth2/tokenPOST令牌端点,支持多种 grant\_type
/uas/oauth2/jwksGETJWKS 端点,分发 RSA 公钥
/uas/oauth2/userinfoGET/POSTUserInfo 端点,返回用户信息
/uas/oauth2/revokePOST令牌撤销端点🤔
/uas/oauth2/introspectPOST令牌内省端点🤔
/uas/connect/logoutGET/POSTOIDC 登出端点🤔

6.2 自定义端点

6.2.1 获取授权码

典型场景:微信环境小程序内部访问 H5(使用 sso 登录)

携带已有的 uas\_access\_token 请求 UAS 获取一次性的 uas_sso_code。

# 调用方:业务微信小程序
POST https://pre-yy.zy.com/uas/auth/code
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {access_token}

authorize_type=sso_auth|mp_auth

# 成功响应
{
    "uas_sso_code": "xxxx",
    "expires_in": 300
}

6.2.2 获取令牌(微信授权码模式)

微信小程序使用此授权模式,用微信 code/phone_code 换取令牌。

# 调用方:业务微信小程序
POST https://pre-yy.zy.com/uas/auth/token
Content-Type: application/x-www-form-urlencoded

grant_type=mp_code|uas_code
&app_id=wxabdckfjdksa
&login_code=login_code
&phone_code=phone_code
&uas_code=uas_code[32位]

# 成功响应
{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "uas_refresh_token": "OpWGgJhVZ...",
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "token_type": "Bearer",
    "expires_in": 7200,
    "scope": "openid profile"
}

6.2.3 验证SSO登录授权码

UCOUT携带

# 调用方:业务微信小程序
POST https://pre-yy.zy.com/uas/auth/sso-verify
Content-Type: application/x-www-form-urlencoded

uas_sso_code=uas_sso_code
&client_id=xxx
&sign=sign
&ts=ts

# 成功响应
{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "uas_refresh_token": "OpWGgJhVZ...",
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "token_type": "Bearer",
    "expires_in": 7200,
    "scope": "openid profile"
}

***

7. 业务术语

术语说明
UASUnified Authentication Service,统一认证服务
pptid通行证账号 ID,用户在"外部通行证"系统中的唯一标识
uas\_login\_codeUAS 授权码,由 UAS 生成,用于微信小程序场景中交换访问令牌
uas\_authorize\_codeUAS 联合认证码,由 UAS 生成,用于联合认证场景中进行身份串联
uas\_access\_tokenUAS 访问令牌,JWT 格式,包含用户身份信息,用于访问受保护资源
uas\_refresh\_tokenUAS 刷新令牌,用于在 access\_token 过期后获取新的 access\_token
id\_tokenOIDC 身份令牌,JWT 格式,包含用户认证信息,供客户端验证用户身份
wechat\_type微信应用类型标识,区分不同微信小程序/公众号
system\_id业务系统标识,与 UCOUT 中的 system\_id 对应
JWKSJSON Web Key Set,JSON Web 密钥集合,用于分发公钥

***

8. 展望与后续演进

  1. PKCE 支持:为公共客户端(SPA、小程序)启用 PKCE(Proof Key for Code Exchange,S256),增加授权码的安全性,防止授权码被截获后被用于获取令牌。
  2. SPA 网页端场景:支持 SPA 网页端的标准 OAuth2.0 授权码模式 + PKCE,SPA 无法安全存储 client\_secret,需通过 PKCE 增强安全性。
  3. 动态配置热加载:将鉴权、降级限流等参数移入 Nacos 配置中心,支持运行时动态调整。
  4. 设备授权模式:支持 OAuth2.0 Device Authorization Grant,适配 IoT 设备、智能终端等无浏览器场景。
  5. SAML 2.0 桥接:通过 UAS 作为 SAML 2.0 Service Provider,实现与现有 SAML 2.0 集成(SSO 已支持 SAML 2.0)。
  6. 自适应认证:根据用户设备、IP、行为等风险因子,动态调整认证强度(如低风险静默登录,高风险要求二次验证)。
  7. 令牌加密:支持 JWT 加密(JWE),保护令牌中的敏感声明。
  8. 管理后台:提供客户端注册管理、审计日志查询、令牌管理等功能的管理后台。
  9. CAS SSO 退役:当所有业务系统迁移到 UAS 后,逐步退役 CAS SSO 服务。