传统MySQL账号的安全模型建立在单一密码之上,只要密码被撞库、被钓鱼或者在日志里泄露,攻击者就能直接拿到数据。多因素身份验证(MFA)通过叠加多种认证因子大幅提升安全性,而MySQL从8.0开始原生支持这一机制,配合PAM认证插件还可以无缝对接企业已有的LDAP目录服务或操作系统用户体系。这篇文章会从原理讲到落地,手把手完成整套配置。

一、理解MySQL的MFA机制与认证策略变量
MySQL 8.0引入了一个关键改动:每个用户账号最多可以挂载三个认证插件,分别对应第一因素、第二因素和第三因素。服务端在处理登录请求时会按顺序逐个校验,任何一个因素失败都会导致整个认证流程拒绝。这与传统只挂一个插件的模式完全不同,相当于把认证从单点变成了链式关卡。
整套机制由系统变量authentication_policy控制,它决定了新创建账号时各因素允许或强制使用的插件类型。默认值是*,,,意思是第一因素可以是任何插件,第二、第三因素可选。生产环境常见的配置是*,authentication_ldap_simple_auth或*,auth_pam,表示第一因素用常规密码,第二因素强制走LDAP或PAM。查看和修改方式如下:
-- 查看当前策略 SHOW VARIABLES LIKE 'authentication_policy'; -- 要求第二因素必须使用PAM认证 SET GLOBAL authentication_policy = '*, auth_pam'; -- 要求三个因素:任意插件 + PAM + 可选空缺 SET GLOBAL authentication_policy = '*, auth_pam,';
需要注意,authentication_policy与已废弃的default_authentication_plugin存在互斥关系,前者优先级更高。建议把策略写进my.cnf的[mysqld]段,避免重启后丢失。另外策略只影响新建账号,存量账号需要用ALTER USER手动追加第二因素。
二、配置PAM认证插件对接系统用户与LDAP
PAM(Pluggable Authentication Modules)是Linux体系下可插拔的认证框架,MySQL的auth_pam插件本质上是把认证请求转发给操作系统的PAM栈,由PAM再去调用背后的passwd、LDAP、Kerberos等模块。这种架构的好处是MySQL本身不感知后端是什么目录服务,运维只需维护PAM配置即可。
第一步是安装并激活插件。插件动态库文件通常位于MySQL安装目录的lib/plugin下,执行:
-- 安装服务端认证插件 INSTALL PLUGIN auth_pam SONAME 'auth_pam.so'; -- 确认插件状态 SELECT PLUGIN_NAME, PLUGIN_STATUS FROM information_schema.PLUGINS WHERE PLUGIN_NAME LIKE '%pam%';
第二步是创建PAM策略文件,保存为/etc/pam.d/mysqld。如果只想对接本地系统用户,内容如下:
# 通过本地密码库校验 auth required pam_unix.so account required pam_unix.so
如果要对接LDAP目录,把pam_unix替换为LDAP模块,并保证MySQL服务器主机上已装好相关依赖:
# 对接LDAP服务器的PAM配置 auth required pam_ldap.so account required pam_ldap.so # /etc/ldap.conf 指向LDAP服务器 # host ldap.ipipp.com # base dc=ipipp,dc=com
第三步是创建MySQL账号。PAM插件要求MySQL用户名与系统用户名或LDAP账号一致,或者使用代理用户机制做映射。最简单的直接对应用法:
-- 创建带双因素的账号:先密码,再PAM CREATE USER 'ops_user'@'%' IDENTIFIED BY 'StrongPass#2024' AND IDENTIFIED WITH auth_pam AS 'mysqld'; -- 给存量账号追加第二因素 ALTER USER 'ops_user'@'%' ADD 2 FACTOR IDENTIFIED WITH auth_pam AS 'mysqld';
这里的AS 'mysqld'指定的是PAM策略文件名,即/etc/pam.d/mysqld去掉目录后的名字。客户端连接时会先提示MySQL密码,再触发PAM对话流程要求输入系统或LDAP密码。
三、使用authentication_ldap_simple直接对接LDAP
除了走PAM间接层,MySQL企业版和部分发行版还提供authentication_ldap_simple插件,直接与LDAP服务器通信,配置更扁平,适合已经标准化AD或OpenLDAP的企业。它支持在认证字符串里指定LDAP服务器地址、基准DN和搜索过滤规则,登录时用户输入LDAP密码即可完成校验。
典型配置流程是先装插件、再设置全局LDAP参数、最后建账号:
INSTALL PLUGIN authentication_ldap_simple SONAME 'authentication_ldap_simple.so'; SET GLOBAL authentication_ldap_simple_server_host = 'ldap.ipipp.com'; SET GLOBAL authentication_ldap_simple_server_port = 389; SET GLOBAL authentication_ldap_simple_bind_base_dn = 'dc=ipipp,dc=com'; SET GLOBAL authentication_ldap_simple_bind_root_dn = 'cn=admin,dc=ipipp,dc=com'; CREATE USER 'ldap_user'@'%' IDENTIFIED BY 'mysql_local_pw' AND IDENTIFIED WITH authentication_ldap_simple AS 'uid=ldap_user,ou=people,dc=ipipp,dc=com';
这种方式的优势在于不依赖操作系统PAM栈,MySQL容器化部署时不需要在镜像里额外维护PAM配置。劣势是功能受限于插件本身,无法像PAM那样叠加双因子硬件、指纹等更复杂的模块。两种方案的选择标准很简单:物理机部署、需要灵活扩展认证链条时用PAM;容器化、认证逻辑单一时用LDAP直连插件。
四、客户端连接方式与常见报错排查
MFA账号的登录体验与普通账号不同,mysql客户端会依次弹出多个密码提示,第一行提示输入MySQL密码,第二行提示输入PAM或LDAP密码。如果使用mysql命令行,需要加--plugin-dir指向客户端插件目录,否则会报Authentication plugin cannot be loaded错误。使用应用程序连接时,推荐MySQL Connector 8.0.27及以上版本,JDBC连接串中通过password1和password2属性分别传入两个因素。
几个高频报错值得提前了解。第一是ERROR 1524: Plugin 'auth_pam' is not loaded,说明服务端插件没装或插件目录权限有问题,检查plugin_dir变量并确认mysqld运行账号对该目录有读权限。第二是认证永远失败但MySQL日志无报错,这时要看系统日志或/var/log/secure里PAM的输出,常见原因是LDAP账号未配置密码或/etc/pam.d/mysqld写错了模块名。第三是Access denied出现在第二因素,需要确认PAM映射的系统用户真实存在,且MySQL的proxy_user相关配置没有冲突。
排查PAM问题最有效的手段是用pamtester工具在数据库主机上直接模拟mysqld的PAM调用,绕开MySQL快速定位是目录服务问题还是数据库配置问题。生产上线前建议先用一个测试账号走完整链路,确认登录日志、审计表都能正确记录双因素事件,再批量迁移业务账号。
五、生产环境落地建议
多因素认证会改变所有客户端的连接行为,直接全量开启容易造成业务中断。稳妥的做法是分三步走:先在测试库验证插件兼容性,再为DBA和管理后台账号启用MFA,最后逐步覆盖应用账号。应用账号如果使用LDAP因素,要评估LDAP服务的可用性——一旦目录服务宕机,所有依赖第二因素的连接都会失败,建议给LDAP配置主备实例,MySQL侧通过负载地址访问。
安全层面还有两点补充。一是MFA因素校验支持与密码过期策略、失败锁定策略叠加,配合FAILED_LOGIN_ATTEMPTS和PASSWORD_LOCK_TIME可以进一步压制撞库行为。二是审计方面,开启audit_log插件后,每次多因素登录都会记录认证结果和触发的插件链,满足等保和内审的留痕要求。整体来看,MFA加LDAP的组合投入成本不高,却能显著提高数据库账号的防护强度,是值得优先落地的安全改造项。
MySQL MFA配置LDAP认证PAM认证模块修改时间:2026-09-16 02:06:51