From 169710f129e8286a422c0fb11d29590e8b6c1e67 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sun, 17 May 2026 22:29:36 +0800 Subject: [PATCH] docs: capture qdreader binding repair lessons --- docs/autman-plugin-rules.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/autman-plugin-rules.md b/docs/autman-plugin-rules.md index 7f8fc46..606cdbf 100644 --- a/docs/autman-plugin-rules.md +++ b/docs/autman-plugin-rules.md @@ -582,7 +582,37 @@ bucketGet("otto", key) - `删除全部` 只删除当前用户账号,不清空全局数据。 - cron/系统触发通常没有用户上下文,是否执行全部账号要显式传 `allUsers` 参数,并在代码和测试里说明。 -### 13.5 安全与测试 +### 13.5 Autman JS 用户身份与历史兜底绑定(QDReader 复盘) + +QDReader 这次踩坑说明:账号 ID 识别成功,不代表 Autman 会话用户绑定一定正确。JS 插件里不能只照 Python 示例写 `sender.getUserID()`,也不能在取不到用户时随便兜底。 + +建议统一写 `currentUserId()`,按顺序尝试: + +1. 官方 ES5 全局函数 `GetUserID()`。 +2. `Sender.GetUserID()`。 +3. 兼容旧/小写 sender 方法:`sender.getUserID()`、`sender.getUserId()`、`sender.getUserid()`、`sender.getSenderID()`、`sender.getFromUserId()` 等。 +4. 明确的用户全局变量:`userId`、`userID`、`senderID`、`senderId`、`fromUserId`、`fromUserID`。 + +不要把 `GetChatID()`、`sender.getChatID()`、`chatId` 当用户 owner。群聊里这是群 ID,会让多个成员绑成同一个 owner,只能用于诊断输出。 + +保存 CK 时的安全策略: + +- 获取不到真实用户 ID:拒绝保存,并输出脱敏诊断,不写 `cookie_json` / `user_bind_json`。 +- `cookie_json[uid]` 不存在但 `user_bind_json[uid]` 还存在:这是手动删桶后留下的孤儿绑定,应清理旧绑定后允许重新保存。 +- `cookie_json[uid]` 和 `user_bind_json[uid]` 都存在,但 owner 是历史兜底标识(如早期 `__qdreader_default_owner__` 或 `chickliu` 这类非数字短标识):管理员触发时可自动修复为当前真实用户,并继续更新 CK。 +- `cookie_json[uid]` 和真实其他用户绑定都存在:必须拒绝覆盖,防止抢绑。 + +这类修复要补回归测试: + +- 官方 `GetUserID()` 可正常绑定。 +- 旧 sender 字段可兼容绑定。 +- 无用户 ID 时拒绝写入。 +- CK 被手动删除但绑定残留时可重新添加。 +- 管理员可修复历史兜底 owner。 +- 非管理员不可修复历史兜底 owner。 +- 真实其他用户绑定仍不可覆盖。 + +### 13.6 安全与测试 - `xxx查询` 的数据来源必须写清楚:如果没有实时接口,就命名为“最近签到记录/最后执行日志”,读取 `last_run_json` 和 `last_result_json`,不要让用户误以为是实时查询。 - 执行动作要同时写批次日志和单账号日志;成功、业务失败、请求异常都要落日志,异常不能只显示在当次回复里。