Date: 2026-09-20 | Spec: spec.md
info_user_device)一台设备一行,device_id 主键;记录该设备最近一次手机号验证通过的登录。
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| device_id | VARCHAR(64) | PK,NOT NULL | 设备唯一标识(App 首启生成持久化,≤64) |
| phone | VARCHAR(20) | NOT NULL | 最近一次验证通过的手机号(账号主键,越南 +84) |
| user_id | BIGINT | NOT NULL | phone 对应的 info_user.user_id |
| create_time | DATETIME | NULL | 首次建立信任时间 |
| update_time | DATETIME | NULL | 最近一次登录刷新时间 |
DDL(写入 updatesql/sql.md,人工执行):
-- 2026-09-20 设备绑定手机号信任表(同设备三方登录免绑,029-device-trust-phone-bind)
CREATE TABLE info_user_device (
device_id VARCHAR(64) NOT NULL COMMENT '设备唯一标识(App首启生成持久化)',
phone VARCHAR(20) NOT NULL COMMENT '本设备最近一次验证通过的手机号',
user_id BIGINT NOT NULL COMMENT '对应用户ID(info_user.user_id)',
create_time DATETIME DEFAULT NULL COMMENT '首次建立信任时间',
update_time DATETIME DEFAULT NULL COMMENT '最近一次登录刷新时间',
PRIMARY KEY (device_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设备-手机号信任表(029)';
selectById(deviceId) 命中 → 更新 phone/user_id/update_time(共用设备换号 = 最近一次覆盖);未命中 → insert,create_time = update_time = now。[不存在] --首次验证登录(带deviceId)--> [信任 phone_A]
[信任 phone_A] --phone_B 在本设备登录成功--> [信任 phone_B](覆盖)
[信任 phone_X] --同号再次登录--> [信任 phone_X](仅刷新 update_time)
| Key | 值 | TTL | 写入点 | 消费点 |
|---|---|---|---|---|
oauth:bind:{tempKey} |
provider@providerUid(现状不变) |
5 min | oauthLogin / LINE 回调 未绑定分支 | oauthBindPhone / oauthDeviceConfirm |
oauth:bind:dev:{tempKey}(新增) |
deviceId(仅 deviceConfirm 分支写入) |
5 min | oauthLogin / LINE 回调 未绑定且设备有信任 | oauthDeviceConfirm |
oauthDeviceConfirm 消费时要求两键齐全,且 dev 值与入参 deviceId 相等,否则按"凭证与设备不匹配"拒绝。info_user_oauth)UNIQUE(provider, provider_uid) 语义不变。一键确认 = 向此表新增记录(provider + providerUid → 设备信任手机号对应 userId),插入逻辑与 oauthBindPhone 相同。
复用现有 maskPhone:长度 ≥8 时返回 前3位 + "****" + 后4位(如 098****4321);长度不足 8 原样返回。DeviceTrustService 提供该方法,InfoUserController 现有私有实现改调共用(行为不变)。
| key | 用途 |
|---|---|
no.oauth.device.confirm |
deviceConfirm 分支的成功提示语 |
no.oauth.device.mismatch |
确认接口:tempKey 非设备确认凭证 / dev 键缺失 / deviceId 不匹配 / 设备信任记录不存在 |