必须先执行SELECT User,Host FROM mysql.user WHERE User = ''确认匿名用户存在,再DELETE FROM mysql.user WHERE User = ''并立即FLUSH PRIVILEGES;若无结果则无需删除,且需排查root空密码等更常见隐患。

查得到才算真存在:先确认匿名用户是否实际存活
很多人一上来就删,结果发现 SELECT User,Host FROM mysql.user; 里压根没空用户名——那删个寂寞。匿名用户的本质是 User = ''(空字符串),不是 NULL,也不是 'anonymous'。MySQL 5.7+ 默认初始化时可能留一个 ''@'localhost',但 MySQL 8.0+ 安装脚本已默认跳过这步;如果你是离线安装或从旧版本升级而来,才更可能遇到。
- 执行
SELECT Host, User FROM mysql.user WHERE User = '';
—— 只查空字符串,不查IS NULL,避免误判 - 如果返回空结果,说明没有匿名用户,后续删除操作可跳过
- 注意:有些运维脚本会把
''@'127.0.0.1'和''@'localhost'当成两个,其实它们都算匿名,都要删
删掉它,但别只删一半:DELETE + FLUSH 缺一不可
只执行 DELETE FROM mysql.user WHERE User = ''; 是无效的——MySQL 不会自动重载权限缓存。你立刻再用 mysql -u '' -h localhost 尝试连接,大概率还能进(尤其在未重启服务的情况下)。
- 必须紧跟着执行
FLUSH PRIVILEGES;
,强制 MySQL 重新读取mysql.user表 - 不要用
DROP USER ''@'localhost':该语法在 MySQL 5.7 中不支持空用户名,会报错ERROR 1396 (HY000): Operation DROP USER failed - 删除后建议立即验证:再次运行
SELECT User,Host FROM mysql.user WHERE User = '';,确保返回空集
root 密码为空?匿名用户可能只是“替罪羊”
很多所谓“匿名登录成功”,其实是 root 用户密码为空导致的:当你执行 mysql -u root 不输密码就进了,误以为是匿名用户在作祟。这种情况比真正匿名用户更常见,也更危险。
- 检查 root 是否无密码:
SELECT User,Host,authentication_string FROM mysql.user WHERE User = 'root';
,若authentication_string为空或为*(MySQL 5.7),说明密码未设 - 设密码(MySQL 5.7):
ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourStrongPass123!';
- 设密码(MySQL 8.0+):
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'YourStrongPass123!';
- 设完务必再执行
FLUSH PRIVILEGES;,否则新密码不生效
离线安装后最容易漏的三件事
离线部署常跳过初始化安全脚本(如 mysql_secure_installation),导致一堆隐患埋着不动,直到被扫描器打中。
-
test 数据库没删:执行
DROP DATABASE IF EXISTS test;
,并删掉对应权限记录:DELETE FROM mysql.db WHERE Db = 'test' OR Db = 'test\\_%';
-
host 限制太宽:检查
root是否只允许'localhost',而非'%';若不需要远程管理,直接删掉所有非localhost的 root 记录 -
没关 skip-grant-tables:检查配置文件
/etc/my.cnf或/etc/mysql/my.cnf里有没有残留的[mysqld]下的skip-grant-tables——有它等于完全放弃权限校验
FLUSH PRIVILEGES 没跑,或者 root 还裸奔,删了匿名用户也白删。










