Files
Hugo/4a-system-design/auth-identity-center.md
T

383 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 认证身份中心设计
## 1. 总体定位
认证身份中心是4A系统的**统一认证入口和账号数据基座**,合并了传统4A中"认证"和"身份"两个模块。核心职责:
- 维护全平台统一的账号数据模型
- 提供多因素认证能力(密码 + 人脸 + SIM卡识别 + 短信验证码)
- 管理用户会话和令牌(JWT签发/验证/刷新)
- 与现网账号平台保持账号数据实时/准实时一致
---
## 2. 数据模型
### 2.1 核心账号表(T_ACCOUNT)
```sql
-- 账号主表
CREATE TABLE T_ACCOUNT (
account_id BIGINT PRIMARY KEY AUTO_INCREMENT,
-- 统一账号标识(与现网账号平台对齐)
uid VARCHAR(64) NOT NULL UNIQUE COMMENT '统一用户ID,与现网平台一致',
login_name VARCHAR(128) NOT NULL UNIQUE COMMENT '登录名',
display_name VARCHAR(256) COMMENT '显示姓名',
-- 身份信息
id_type TINYINT NOT NULL DEFAULT 1 COMMENT '身份类型:1-内部员工 2-外包 3-第三方 4-临时',
employee_id VARCHAR(64) COMMENT '工号',
org_code VARCHAR(64) COMMENT '所属组织编码',
org_path VARCHAR(512) COMMENT '组织全路径, 如:省公司/市公司/部门',
-- 联系方式
mobile VARCHAR(32) COMMENT '手机号',
email VARCHAR(256) COMMENT '邮箱',
-- 认证凭据
password_hash VARCHAR(256) COMMENT '密码哈希(BCrypt)',
password_salt VARCHAR(64) COMMENT '密码盐值',
password_version INT NOT NULL DEFAULT 1 COMMENT '密码策略版本号',
need_reset_password TINYINT NOT NULL DEFAULT 0 COMMENT '需要重置密码:0-否 1-是',
-- 人脸信息
face_template_id VARCHAR(128) COMMENT '人脸模板ID(金科侧)',
face_registered TINYINT NOT NULL DEFAULT 0 COMMENT '是否已注册人脸',
-- SIM卡信息
sim_imsi VARCHAR(64) COMMENT 'SIM卡IMSI(互联网SIM卡识别用)',
sim_phone VARCHAR(32) COMMENT 'SIM卡关联手机号',
sim_verified TINYINT NOT NULL DEFAULT 0 COMMENT 'SIM卡是否已验证',
-- 状态管理
status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:0-禁用 1-正常 2-锁定 3-过期',
lock_reason VARCHAR(256) COMMENT '锁定原因',
last_login_ip VARCHAR(64) COMMENT '最后登录IP',
last_login_time DATETIME COMMENT '最后登录时间',
login_fail_count INT NOT NULL DEFAULT 0 COMMENT '连续登录失败次数',
unlock_time DATETIME COMMENT '自动解锁时间',
-- 有效期
effective_date DATE COMMENT '生效日期',
expire_date DATE COMMENT '失效日期',
-- 审计字段
created_by VARCHAR(64) NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_by VARCHAR(64) NOT NULL,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除:0-未删除 1-已删除',
INDEX idx_uid (uid),
INDEX idx_login_name (login_name),
INDEX idx_org_code (org_code),
INDEX idx_mobile (mobile),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账号主表';
```
### 2.2 账号扩展属性表(T_ACCOUNT_ATTR)
支持与现网平台扩展属性的灵活映射,避免频繁改表。
```sql
CREATE TABLE T_ACCOUNT_ATTR (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
account_id BIGINT NOT NULL COMMENT '关联账号ID',
attr_key VARCHAR(128) NOT NULL COMMENT '属性键',
attr_value VARCHAR(1024) COMMENT '属性值',
attr_type VARCHAR(32) COMMENT '值类型:string/number/date/json',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_account_attr (account_id, attr_key),
INDEX idx_attr_key (attr_key, attr_value(128))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账号扩展属性表';
```
### 2.3 与现网账号平台拉齐方案
现网账号平台通常是多系统异构的(HR系统、OA、运维平台等各有账号体系)。拉齐策略:
```
┌─────────────────────────────────────────────────────────────────┐
│ 现网账号平台(多源) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ HR系统 │ │ OA系统 │ │ 运维平台 │ │ 第三方接入 │ │
│ │ (工号为主)│ │(邮箱为主) │ │ (SSH用户) │ │ (API对接) │ │
│ └─────┬────┘ └────┬─────┘ └─────┬────┘ └──────┬───────┘ │
│ │ │ │ │ │
│ └──────┬─────┴──────┬──────┴──────────────┘ │
│ │ │ │
│ ┌──────▼────────────▼──────┐ │
│ │ 账号同步适配器层 │ │
│ │ (定时拉取 + 变更推送) │ │
│ │ 策略:现网→自研单向同步 │ │
│ │ 冲突:以现网最新时间为准 │ │
│ └───────────┬──────────────┘ │
│ │ │
│ ┌───────────▼──────────────┐ │
│ │ 自研T_ACCOUNT主表 │ │
│ │ (以uid为统一标识) │ │
│ │ 额外字段:sync_source │ │
│ │ sync_version │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
**同步策略关键点**:
1. **单向同步**:现网平台 → 自研系统(防止自研的修改反向污染现网)
2. **标识统一**:`uid` 字段作为跨系统唯一标识,映射现网各系统 ID
3. **定时+事件驱动**:
- 定时全量同步(每天凌晨)
- 变更事件订阅(MQ消息,实时增量同步)
- 手动触发全量同步(管理员操作)
4. **冲突处理**:
- 自研系统只读现网字段,不做覆盖
- 现网字段为主版本,自研扩展字段(如人脸模板ID)为从版本
- 时间戳精度到毫秒级,解决并发冲突
5. **挂载表记录同步日志**:T_ACCOUNT_SYNC_LOG 记录每次同步的变更明细
---
## 3. 认证能力接入
### 3.1 认证流程总图
```
┌──────────────────────┐
│ 统一认证入口 │
│ POST /api/v1/auth │
└──────────┬───────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
┌─────▼─────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ 密码认证 │ │ 人脸认证 │ │ SIM认证 │
│ provider │ │ provider │ │ provider │
└─────┬─────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└────────┬────────┴────────┬────────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ 认证成功 │ │ 认证失败 │
│ → 生成令牌 │ │ → 记录失败 │
│ → 返回JWT │ │ → 触发告警 │
└─────────────┘ └─────────────┘
```
### 3.2 密码认证
- **技术选型**:BCrypt(自适应哈希,cost factor=10-12)
- **策略**:
- 支持密码复杂度策略(长度/大小写/特殊字符组合)
- 支持密码历史管理(禁止使用最近N次密码)
- 连续失败N次后锁定账号 T 分钟
- 支持首次登录强制改密
- **接口**:标准 OAuth2 Password Grant + 自定义扩展
### 3.3 金科人脸识别接入
**集成方案**:
```yaml
# 金科人脸识别对接配置
face_recognition:
provider: "jinke"
api_base: "https://face-api.chinamobile.com/v2"
auth_mode: "aksk" # API Key + Secret Key 认证
timeout_ms: 5000
retry:
max_attempts: 2
backoff_ms: 200
endpoints:
verify: "/face/verify" # 1:1 人脸验证
detect: "/face/detect" # 人脸检测
register: "/face/register" # 人脸模板注册
delete: "/face/template/delete" # 删除人脸模板
liveness:
enabled: true # 活体检测开关
mode: "action" # action: 动作指令式, flash: 闪光
```
**认证流程**:
1. 客户端采集人脸图片 → 上传至自研后台
2. 自研后台调用金科 `/face/detect` 检测有效性(活体检测)
3. 通过后调用 `/face/verify` 传入用户 `uid` + 人脸图片
4. 金科返回置信度和匹配结果(阈值 >= 0.85 视为通过)
5. 自研后台记录认证日志,签发JWT
### 3.4 互联网SIM卡识别
**能力说明**:
- 利用运营商网关能力,识别用户手机号与SIM卡IMSI的绑定关系
- 用户通过蜂窝网络访问时,网关可携带SIM卡信息
- 实现"无感认证"——用户只需打开页面即可自动识别身份
**接入方案**:
```
用户手机(蜂窝网络) ──→ 运营商网关 ──→ 自研4A网关
↑ ↑
HTTP Header携带 解析Header提取
IMSI/MSISDN SIM信息,与账号
T_ACCOUNT.sim_imsi
做匹配验证
```
**技术要点**:
1. 依赖运营商网关配置(需与网络部协调开通)
2. 作为辅助认证因子,不可单独作为强认证手段
3. 需配合设备指纹、IP地理位置等信息做风险判断
4. 当SIM信息与预注册信息不一致时,触发二次认证(短信验证码)
### 3.5 消息中心短信接入
**集成方案**:
```yaml
sms:
provider: "message_center" # 中国移动消息中心
api_base: "https://msg-center.chinamobile.com/api"
app_id: "${SMS_APP_ID}"
app_secret: "${SMS_APP_SECRET}"
endpoints:
send: "/sms/send"
batch_send: "/sms/batch_send"
query_status: "/sms/status/{msg_id}"
features:
template: true # 使用短信模板(防篡改)
signature: "【中国移动】"
expiry_minutes: 5 # 验证码有效期5分钟
```
**流程**:
1. 发送验证码:生成6位数字验证码 → 写入 Redis(key=sms:code:{mobile}, TTL=300s)→ 调用消息中心API下发
2. 验证:用户提交验证码 → 查 Redis 比对 → 正确则完成认证
3. 限制策略:60秒内不可重复发送,每日上限10次
### 3.6 多因素认证组合策略
```
┌──────────────────────────────────────────────────────────────────┐
│ MFA策略配置(可动态调整) │
│ │
│ 场景类型 │ 认证因子组合 │
│ ──────────────────┼─────────────────────────────────────────── │
│ 内部网络登录 │ 密码 (单因素) │
│ 远程VPN登录 │ 密码 + 短信验证码 (双因素) │
│ 堡垒机登录 │ 密码 + 人脸/SIM (双因素) │
│ 敏感操作确认 │ 已登录令牌 + 短信验证码 (双因素) │
│ 管理员操作 │ 密码 + 人脸 + 短信验证码 (三因素) │
│ SIM卡网关识别 │ SIM识别 (零操作) │
└──────────────────────────────────────────────────────────────────┘
```
---
## 4. 令牌与会话管理
### 4.1 JWT令牌设计
```json
{
"access_token": {
"header": {"alg": "RS256", "typ": "JWT", "kid": "2026-01"},
"payload": {
"sub": "uid_00123",
"iss": "4a-self",
"aud": "4a-resource-centers",
"exp": 3600,
"iat": 1700000000,
"jti": "unique-token-id-abc123",
"auth_context": {
"mfa_level": 2,
"auth_methods": ["password", "sms"],
"session_id": "sess_xyz789"
},
"roles": ["operator", "auditor"]
},
"sign": "RS256_signature..."
},
"refresh_token": {
"expiry": 86400 * 7,
"rotation": true
}
}
```
- **签名算法**:RS256(非对称),access_token 和 refresh_token 使用不同密钥对
- **有效期**:access_token 1小时,refresh_token 7天(支持滑动刷新)
- **吊销机制**:Redis 维护黑名单(`jti:revoked`),注销/改密后立即使所有token失效
### 4.2 会话状态存储
```
Redis Key 设计:
4a:session:{session_id} → Session对象(用户信息、MFA等级、设备指纹)
4a:token:jti:{jti} → 令牌元数据(issuer_ip、issued_at、status)
4a:token:user:{uid} → 用户当前有效令牌列表
4a:token:blacklist:{jti} → 吊销令牌集合(TTL = token有效期)
4a:sms:code:{mobile} → 短信验证码(TTL = 300s)
4a:login:fail:{uid} → 登录失败计数(TTL = 锁定周期)
```
---
## 5. 接口规范
### 5.1 认证接口
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/v1/auth/login` | POST | 统一登录入口,请求体指定认证方式 |
| `/api/v1/auth/refresh` | POST | 刷新access_token |
| `/api/v1/auth/logout` | POST | 登出,吊销令牌 |
| `/api/v1/auth/check` | GET | 校验令牌有效性 |
| `/api/v1/auth/sms/send` | POST | 发送短信验证码 |
| `/api/v1/auth/face/register` | POST | 注册人脸模板 |
| `/api/v1/auth/sim/verify` | POST | SIM卡验证 |
### 5.2 账号管理接口
| 接口 | 方法 | 说明 |
|------|------|------|
| `/api/v1/accounts` | GET | 分页查询账号列表 |
| `/api/v1/accounts/{uid}` | GET | 查询单个账号详情 |
| `/api/v1/accounts` | POST | 创建账号(同步到现网需审批) |
| `/api/v1/accounts/{uid}` | PUT | 更新账号信息 |
| `/api/v1/accounts/{uid}` | DELETE | 禁用/删除账号 |
| `/api/v1/accounts/{uid}/password` | PUT | 修改密码 |
| `/api/v1/accounts/{uid}/status` | PATCH | 修改账号状态 |
| `/api/v1/accounts/sync/trigger` | POST | 手动触发全量同步 |
| `/api/v1/accounts/sync/log` | GET | 查询同步日志 |
### 5.3 响应格式
```json
// 成功响应
{
"code": 0,
"message": "success",
"data": {},
"request_id": "req-uuid-xxx"
}
// 错误响应
{
"code": 40101,
"message": "invalid_credentials",
"detail": "密码错误,还剩3次尝试机会",
"request_id": "req-uuid-xxx"
}
```
---
## 6. 与泰岳版比对关注点
| 项 | 自研方案 | 泰岳方案(推测) | 验证方法 |
|----|---------|-----------------|---------|
| 密码存储 | BCrypt + 多代盐值 | 厂商自研加密模块 | 黑盒:记录认证耗时 |
| 会话管理 | Redis + JWT | 可能为DB + Session | 比较并发下Session创建吞吐 |
| 认证流程扩展 | Provider模式,可插拔 | 模块化程度未知 | 接入新因子时的改动量对比 |
| 多因素组合 | 策略引擎(DSL配置) | 可能硬编码 | 配置灵活度对比 |
| 账号同步 | 适配器模式对接多源 | 可能单源集中 | 同步延迟和完整性对比 |