laoyang
|
ebaed21920
|
v57:令牌升级为「设备会话」(24h 滑动续期 / 每账号 10 台 / 网页端远程退出)
用户 2026-10-17 定的模型:
· 一次登录 = 一台设备一条会话;同一台设备重登,旧令牌立即作废
· 24 小时滑动续期(一直联网就不用每天输密码);离线超 24h 只锁界面、不删数据
· 网页端「个人设置 → 设备管理」能看见都有谁在登录,并能把丢了的那台踢掉
· 每账号最多 10 台,超了让用户先踢旧的
服务端配套:
· api_tokens 加 device_id / device_name / platform / app_version / last_ip
+ idx_api_device;历史令牌回填 legacy-<id>(不回填 = 踢不掉的幽灵会话)
· ApiToken:issueDevice / listDevices / revokeDevice / revokeOthers / revokeCurrent
+ 滑动续期(剩余不足 4h 才写库);verify 同时返回数字键与关联键(三处调用方在用)
· 新增 /api/v1/logout、/api/v1/devices;ping 报 features.device_session
· 登录不再读 days(0 = 永不过期会绕过 24h 这条线);超限回 409 且**不动任何一行**
· 老客户端兜底固定槽位 auto-unknown(随机设备号会撞满 10 台把账号锁死)
· Schema 34 → 35
顺带:首页近期任务/往年的今天(Home::memories)、名册派生字段口径统一。
验证:设备会话探针 56/0、设备管理渲染 22/0、登录全链路 30/0、反向验证 12/0、
e2e 1519/0、静态断言本地空跑 357/0、线上 /api/v1/{ping,devices,logout} 复核通过。
|
2026-10-18 03:34:47 +08:00 |
|
laoyang
|
13a5d08696
|
v45 API 补录:手机号登录换令牌 + 我的名册 / 家谱接口 + 出口层敏感字段脱敏
🔴 为什么现在才提交(这是「补录」,代码早已上线并验证):
v45 第三/第四批当时,同一工作区里有**并行的鸿蒙端工作流**正在改这个文件
(手机号登录换令牌、media.php 的 ?token=)。按「绝不把别人正在写的裹进
自己的提交」的纪律,那次只提交了自己的 5 个文件,本文件被**故意留下**。
此后文件静止约 25 小时、端上工作流也已收尾 ⇒ 现在补录,让仓库与线上一致
(线上 md5 = 本地 md5,deploy 是从工作树打包的,所以线上一直是这份)。
① `POST /api/v1/login` —— 手机号 + 密码 → API 令牌
原先 App 只能「先去网页签发令牌、再手动粘贴」,能用但没法给别人用。
与网页登录有意不同:不建会话(API 无状态);限流落**文件**
(`sys_get_temp_dir()/fb_login_<sha256(ip|phone)>.json`,60s 窗口 / 5 次)
而不进 $_SESSION;失败**统一**提示(不区分「没这个人」与「密码错」,
否则接口成了手机号是否已注册的探测器);有效期用**服务端时间**算。
成功时顺带 `Calendar::seedDefaults()`(全新安装的兜底)。
② `GET /api/v1/roster` —— 「**我**名册里的人」(我加的 + 别人分享的)
与 `/people`(全家 801 人 = 通讯录底账)区分开:App 名册页要用这个,
否则一屏 800 人且是「别人的通讯录」。组装**照抄 Web 端 index.php 的
people 分支**(同一套类/判据):Person::roster → Kinship::label /
Nickname::display / PersonQuery::phonePlain / PersonQuery::birthdaysOf /
PersonTag::mapFor / Pinyin::initials,外加标签云与标签词表。
⚠️ 复用这些类而非另写,否则会「网页搜得到、App 搜不到」。
③ `GET /api/v1/kin` —— 家谱(以我为中心的关系图)
用 `Kinship::familyMap($fam,$pid,$people,2,2)`,与 Web 端 kin/tree.php
同一套 ⇒ 端上与网页的亲属关系必然一致。按代数排序,拍平直接关系字段。
④ 🔴 信息泄露修复:`stripSensitivePerson()`
`Person::all()` / `Person::roster()` 都是 `SELECT p.*`,把
`phone_hash` / `phone_encrypted` / `id_card_encrypted` / `birthday_id_card` /
`birthday_lunar*` 一路吐给 App。前两个是 AES 密文(离线爆破材料),
`phone_hash` 是「手机号是否属于这个家」的判定键。
⇒ 在 **API 出口层**脱敏(列表 / 详情 / 新建 / PATCH 四个出口都套)。
⚠️ **不能改 `Person::all()` 本身**:网页端确实在用(ContactImporter 靠
phone_hash 去重、PersonQuery 靠 phone_encrypted 按手机号搜)
⇒ 网页要、App 不要 ⇒ 差异落在出口层。
线上验证(全绿):GET login→405 / 缺参→422 / 错密码→401「手机号或密码不对」
/ 不存在的手机号→**同样的** 401 与提示 / 连续错→第 6 次起 429 / 名册 800 人 /
标签云 15 个 / 称谓正确(爸爸→父亲…)/ 手机号解密正确 / 生日阴阳历 /
首字母 ypzbb / 6 个敏感字段全去除(列表与详情都验)。
|
2026-10-14 09:41:34 +08:00 |
|