mysql 8.0社区版不支持原生2fa或内置ldap,必须通过auth_pam插件委托给系统pam链式处理(如pam_sss.so+ pam_google_authenticator.so);双密码仅能用alter user ... retain current password实现,非多因素验证。

MySQL 8.0 社区版不支持原生双重认证(2FA)或内置 LDAP 集成,所谓“配置双重认证”实际是把第二因子或目录服务验证委托给外部系统完成;你不能靠一条 CREATE USER 或改个配置项就启用 TOTP、短信或 LDAP 登录。
用 ALTER USER RETAIN CURRENT PASSWORD 实现双密码(不是双因素)
这是唯一能平滑切换生产密码的机制,但注意:它只是两个密码并存,不是多因素验证。
-
SET PASSWORD完全不支持双密码,执行后会无条件清空辅助密码,导致应用随机断连 - 必须先确认账户当前密码非空:
SELECT user, host, authentication_string FROM mysql.user WHERE user = 'u' AND host = 'h';,返回值不能为NULL或空字符串 - 语句必须在主库执行,且需等所有从库
Seconds_Behind_Master = 0后再切应用连接 - 双密码不会自动过期,必须显式执行
DISCARD OLD PASSWORD才能清理——漏掉这步,半年前的密码仍可登录 - 不能在事务中执行,
ALTER USER是隐式提交,包裹BEGIN/COMMIT没意义还易误导
社区版集成 LDAP 只能走 PAM 链路(不是插件直连)
官方社区版 MySQL 8.0+ 不含 authentication_ldap_sasl 或 authentication_ldap_simple 插件,INSTALL PLUGIN 会直接报错“Plugin not loaded”或文件不存在。
- 可行路径只有一条:启用
auth_pam插件,把认证请求交给操作系统 PAM 框架处理 -
/etc/pam.d/mysqld必须存在、权限为644、属主root:root;内容顺序不能错,例如:auth [success=ok default=ignore] pam_sss.so必须在auth [success=done default=bad] pam_google_authenticator.so前 - MySQL 用户名必须与 LDAP 中的
uid完全一致(大小写、特殊字符都不能差),否则 PAM 根本收不到正确用户名去查密钥 -
mysql进程用户需能读取/var/lib/google-authenticator/${USER},通常要加 ACL 或把mysql用户加入对应组 - SELinux 启用时,
setsebool -P authlogin_nsswitch_use_ldap on和setsebool -P allow_user_mysql_connect on往往必须同时设置
CREATE USER 必须严格匹配 PAM 认证语法
一旦启用 PAM,MySQL 就不再处理 IDENTIFIED BY 字段,任何混用都会导致认证失败。
- 正确写法:
CREATE USER 'alice'@'%' IDENTIFIED WITH auth_pam AS 'mysqld';——AS 'mysqld'必须存在,且值要和/etc/pam.d/下的文件名一致 - 错误写法:
CREATE USER 'alice'@'%' IDENTIFIED BY 'xxx' IDENTIFIED WITH auth_pam AS 'mysqld';—— MySQL 会优先解析IDENTIFIED BY并忽略后续,最终创建出一个用mysql_native_password插件的用户 - 不能用
GRANT ... IDENTIFIED BY替代CREATE USER,该语法在 8.0+ 已废弃,且不支持IDENTIFIED WITH - 如果用户已存在,必须先
DROP USER再重建,ALTER USER ... IDENTIFIED WITH不支持从原生插件切换到auth_pam
真正容易被忽略的是:PAM 链式调用中任意一环失败,整个认证就终止,但 MySQL 日志里只会记 Access denied for user,看不出是 LDAP 连不上、还是 Google Authenticator 密钥文件权限不对、或是时间不同步导致 TOTP 验证失败。调试必须查 /var/log/secure 或 journalctl -u mysqld,而不是只盯 MySQL 的 error log。











