$cfg['Servers'][$i]['AllowNoPassword'] = false仅禁用phpMyAdmin前端密码字段留空提交,不阻止MySQL服务端空密码用户登录;须清除mysql.user表中authentication_string为空的账户、启用validate_password插件并禁用skip-grant-tables。

为什么$cfg['Servers'][$i]['AllowNoPassword'] = false不能真正禁用空密码
这个配置项只控制 phpMyAdmin 登录页是否允许用户留空密码字段提交,它不碰 MySQL 服务端的实际认证逻辑。只要 mysql.user 表里存在 authentication_string 为空的用户(比如初始化时没设密的 root@localhost),攻击者绕过 phpMyAdmin、用命令行或任意客户端连上就能直接登录。所以光关这个开关是假安全。
必须从 MySQL 服务端清除空密码用户
登录 MySQL 后立即执行:
SELECT user, host, plugin, authentication_string FROM mysql.user WHERE authentication_string = '' OR authentication_string IS NULL;
如果返回非空结果:
- 对每个账户执行
ALTER USER 'username'@'host' IDENTIFIED BY 'strong_password'; - 若该账户纯属测试残留,直接
DROP USER 'username'@'host'; - 检查
plugin列:若为auth_socket(常见于 Ubuntu/Debian),说明它根本不校验密码,而是依赖系统用户——这不是空密码问题,但同样危险,应改用caching_sha2_password并设密
防止空密码再生的硬性约束
仅清理一次不够,得堵住入口:
- 启用
validate_password插件:INSTALL PLUGIN validate_password SONAME 'validate_password.so';,再运行SET GLOBAL validate_password.policy = MEDIUM;—— 此后ALTER USER ... IDENTIFIED BY ''会直接报错ERROR 1819 - 确认
skip-grant-tables没被误写进my.cnf或启动参数,该模式下所有认证全 bypass - phpMyAdmin 配置中仍保留
$cfg['Servers'][$i]['AllowNoPassword'] = false;,作为前端拦截层,但别把它当主力防线
多服务器场景下最容易被忽略的坑
动态生成 $cfg['Servers'] 数组时,如果某台服务器配置漏了 'auth_type' => 'cookie' 或填了 'auth_type' => 'config' 且附带了空 'password' => '',phpMyAdmin 可能静默降级到无认证连接——此时哪怕你关了 AllowNoPassword,它也会把空密码当合法凭据透传过去。务必确保每个 $cfg['Servers'][$i] 子数组都显式声明 'auth_type',且不用 config 模式存明文密码。



















