本报告分析了在浏览器插件中实现一次性密码(OTP)自动填充功能所需的需求和代码变更。此功能依赖于 KeePassRPC 后端的更新,该更新已将 OTP 值暴露给客户端。
KeePassRPC 插件已进行修改,在 Entry 数据模型中包含了一个公开的 Otp 字符串字段。用于获取条目的 JSON-RPC 响应现在将包含此字段。
我们需要更新 TypeScript 接口,以便将 JSON-RPC 响应映射到前端时能够识别新的 otp 字段。
- 文件:
src/common/model/KPRPCDTOs.ts - 操作: 在
EntryDto类中添加otp属性。
export class EntryDto {
// ... 现有字段
title: string;
formFieldList: FieldDto[];
otp?: string; // 新增此字段
}内部的 Entry 模型需要接收此新数据并将其转换为 Field 对象,以便自动填充逻辑可以使用它。
- 文件:
src/common/model/Entry.ts - 操作: 更新
fromKPRPCEntryDTO方法以创建 OTP 字段。
// 在 Entry.fromKPRPCEntryDTO 方法中:
// ... 现有代码 ...
const firstPasswordIndex = unsortedFields.findIndex(f => f.type === "password");
// 添加此代码块
if (entryDto.otp) {
const otpField = new Field({
name: "OTP", // 显示名称
type: "otp",
value: entryDto.otp,
locators: [
new Locator({
name: "otp",
id: "otp",
type: "otp" // 这将有助于匹配逻辑
})
]
});
// 添加到 sortedFields
sortedFields.push(otpField);
}
// ... 现有代码 ...目前的表单填充逻辑依赖于严格的类型匹配。我们需要针对 OTP 字段放宽这一限制,并增加自动刷新功能。
- 文件:
src/page/formFilling.ts - 操作 1: 更新
calculateFieldMatchScore以支持更广泛的 OTP 匹配(包括password类型和标签上下文)。
// 定义关键词
const OTP_KEYWORDS = [
"otp", "totp", "2fa", "token", "code", "verification",
"验证码", "动态密码", "一次性密码", "安全码", "动态安全码", "passwd1"
];
const OTP_LABEL_KEYWORDS = [
"mfa", "device", "serial", "google authenticator", "authenticator",
"验证", "虚拟", "设备"
];
// 在 calculateFieldMatchScore 方法中:
// 1. 类型匹配放宽:允许 OTP 匹配 text, password, tel, number
if (formField.type !== dataField.type) {
const isOtpMatchingText = dataField.type === "otp" &&
(formField.type === "text" || formField.type === "password" ||
formField.type === "tel" || formField.type === "number");
if (!isOtpMatchingText) return 0;
}
// 2. 评分逻辑增强
if (dataField.type === "otp") {
let otpScore = 0;
// ... 获取 name, id, labels, placeholder ...
// 强信号: autocomplete="one-time-code" (+100)
// 强信号: 标签或占位符包含上下文关键词 (MFA, Device 等) (+80)
// 启发式: Name/ID 包含 OTP 关键词 (+50)
// 惩罚: 看起来像用户名或搜索字段 (-100)
score += otpScore;
} else {
// 防御性:普通字段如果匹配到了 OTP 关键词,给予惩罚 (-100),防止误填
}- 操作 2: 实现 OTP 自动刷新机制。
// 在 FormFilling 类中:
// 调度刷新
private scheduleOtpRefresh() {
// 计算距离下一个 30秒 周期的时间 + 2秒缓冲
// setTimeout 触发后调用 findMatchesInThisFrame 重新获取数据
}
// 在 fillMatchedFields 中检测到 OTP 填充后调用 scheduleOtpRefresh虽然自动填充是主要目标,但在弹出窗口或上下文菜单中显示 OTP 可能也是需要的。
- 由于我们将 OTP 作为
Field添加到了Entry对象中,只要 UI 遍历并显示entry.fields,且能正确处理otp字段类型(通常默认为文本显示),它就应该自动出现。 - 文件:
src/common/model/Field.ts- 确保getDisplayValue能处理otp类型。
- 修改
src/common/model/KPRPCDTOs.ts。 - 修改
src/common/model/Entry.ts。 - 修改
src/page/formFilling.ts。 - 构建并使用修改后的 KeePassRPC 插件进行测试。