用户在 WebUI(电脑版或手机版)的“个人账号 → 二步验证”中自行选择开启,无需管理员授权。
- 输入当前密码,开始绑定。
- 使用支持 TOTP 的认证器扫描二维码,或手动输入密钥。二维码在服务器本地生成。
- 输入认证器中的 6 位验证码,确认后才会启用验证。绑定页面 10 分钟内有效。
- 立即保存页面显示的 10 个一次性恢复码。恢复码仅显示一次,数据库只保存摘要。
开启后,WebUI 先校验账号密码,再进入独立验证码页面;完成前没有已登录 Cookie。浏览器挑战 5 分钟有效,并绑定账号的安全标记。“保持登录”只影响完成验证后的会话,每次重新登录仍需验证。手机扫码、App 打开网页和移动设备登录票据也会要求验证。Android 与 Wear OS 会弹出验证码输入界面,支持切换到恢复码;验证期间密码只留在当前登录协程内,取消或 5 分钟超时后释放。
验证码采用 RFC 6238 的 SHA-1、6 位、30 秒配置,允许前后各一个时间窗口。成功使用的时间窗口无法再次使用,包括刚刚用于绑定确认的验证码;请等待认证器显示下一组数字。密码或验证码连续失败共 8 次会锁定账号 10 分钟,单独输入正确密码不会清除验证码的失败次数。认证器和服务器应保持自动校时。
认证器丢失时,在登录页选择“使用一次性恢复码”。每个恢复码只接受一次,并发请求也只能成功一次。登录后可用当前密码和另一个恢复码关闭验证,再重新绑定认证器并保存新恢复码。管理员重置密码不会关闭用户的二步验证。
开启或关闭验证会轮换账号安全标记、撤销设备会话、移除浏览器推送订阅,并同步插件授权镜像;当前正在设置的网页会保留登录,其他网页会话需重新登录。API Key 保持原有行为,自动续期已登录设备时不重复提示验证码。
TOTP 密钥通过账号 ID 绑定的 ASP.NET Core Data Protection 保护后写入数据库。请保留数据库同级的 keys/ 密钥环。本地备份 v6 保留加密密钥、验证状态、已用验证码窗口和剩余恢复码摘要;口令加密导出包会携带可移植密钥,导入另一台服务器时重新加密。如果 keys/ 丢失或被替换,已有账号的密钥无法解密,此时认证器验证码在本机也无法校验,只能用恢复码登录。导出不会因此失败:这些账号保留原密文导出,迁移后状态不变;系统设置页会列出受影响账号,请让他们用恢复码登录后关闭并重新绑定。v1–v5 的旧配置包继续兼容。迁移由服务启动时自动执行,原有账号默认关闭二步验证。
实现参考:RFC 6238。