服务器MFA与密钥双重认证本质是解耦并强制串联“你知道的”(密码)、“你拥有的”(私钥)和“你生成的”(动态口令)至少两项,确保各因素独立生效、不可绕过或替代;SSH需PAM+TOTP组合校验,MySQL依赖PAM插件桥接,Web层须JWT绑定设备指纹闭环验证,且所有密钥须加密存储、严控生命周期。

SSH 登录:密钥 + TOTP 组合强制校验
这是最常见也最稳妥的落地方式,依赖 Linux PAM 和 OpenSSH 协同控制流程:
- 保留公钥认证作为第一道身份凭证(
PubkeyAuthentication yes),禁用密码登录(PasswordAuthentication no) - 在
/etc/pam.d/sshd中添加一行:auth [success=ok default=bad] pam_google_authenticator.so nullok user=root,确保只有通过 TOTP 校验才允许继续 - 启用挑战响应:
ChallengeResponseAuthentication yes,否则 PAM 的 OTP 校验不会触发 - 每个用户需独立运行
google-authenticator生成密钥,并保存在~/.google_authenticator(权限设为600) - 重启 sshd 后,登录流程变为:输入用户名 → 自动匹配密钥 → 成功后立即提示输入 6 位动态码
MySQL 数据库:PAM 插件桥接 TOTP
MySQL 原生不支持手机端 TOTP,必须借操作系统 PAM 层完成第二因素校验:
- 确认 MySQL 版本 ≥ 8.0.27,执行
INSTALL PLUGIN authentication_policy SONAME 'authentication_policy.so'; - 安装
authentication_pam插件:INSTALL PLUGIN authentication_pam SONAME 'auth_pam.so'; - 创建系统级 PAM 配置
/etc/pam.d/mysql,内容包含pam_unix.so(校验本地账户)和pam_google_authenticator.so(读取用户密钥文件) - 建用户时绑定 PAM service:
CREATE USER 'mfa_user'@'%' IDENTIFIED WITH authentication_pam AS 'mysql'; - 客户端连接需加参数:
--default-auth=mysql_clear_password,否则握手阶段无法传递明文验证码
Web 应用层:JWT + 绑定设备指纹
面向浏览器或 API 的访问,不能只靠登录页弹窗加个验证码,而要让第二因素参与令牌签发与校验闭环:
- 用户完成账号密码登录后,跳转至独立 MFA 页面,扫描 QR 码绑定 TOTP 设备
- 二次验证通过后,认证服务签发 JWT,其中必须携带
device_fingerprint(如 UA+IP+Canvas Hash 混合哈希)和otp_verified: true - 资源服务校验 JWT 时,除检查签名与过期时间外,还需比对当前请求的设备指纹是否与令牌内一致
- 敏感操作(如修改密码、导出数据)要求令牌中
otp_verified为 true 且距签发时间 ≤5 分钟
密钥安全与密钥生命周期管理
私钥本身是高危资产,若未妥善保护,MFA 就形同虚设:
- SSH 私钥必须加密存储(
ssh-keygen -t ed25519 -a 100 -C "user@host"),口令长度 ≥12 位,且不与任何其他系统口令重复 - 数据库连接密钥、API 密钥等不得硬编码在配置文件中,应通过 secrets manager(如 HashiCorp Vault)注入,访问需 RBAC 控制
- TOTP 密钥须 Base32 编码、长度 ≥32 字节,加密后存入数据库(推荐 AES-GCM),严禁明文、日志回显或前端返回
- 用户更换设备或丢失密钥时,必须通过离线审批流程重置,而非仅靠邮箱或短信自助恢复

















