查空密码账户需检查authentication_string是否为空、'*'或系统占位符,排除mysql.session等内置账号;auth_socket用户免密登录需单独识别;过期账号需结合default_password_lifetime变量判断。

查空密码账户:直接看 authentication_string 是否为空或占位符
MySQL 5.7 及以后版本不再用 password 字段存密码,而是统一用 authentication_string。空密码不等于字段为 '',更常见的是值为 '*'、'' 或 '*THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE'(系统保留占位符)。执行以下语句可定位风险账号:
SELECT user, host, authentication_string FROM mysql.user WHERE authentication_string = '' OR authentication_string = '*' OR authentication_string LIKE '*THISISNOTAVALID%';
注意:mysql.session 和 mysql.sys 这类内置管理账号的 authentication_string 固定是占位符,属于正常现象,不用处理。
识别 auth_socket 认证用户:这类账号根本没设密码,但能本地免密登录
Ubuntu/CentOS 新装 MySQL 常见情况:root 用户认证插件是 auth_socket,此时 authentication_string 字段为空或无效,且你无法用 ALTER USER ... IDENTIFIED BY 直接设密码——会报错 ERROR 1396 (HY000): Operation ALTER USER failed。查这类账号用:
SELECT user, host, plugin FROM mysql.user WHERE plugin = 'auth_socket';
典型结果是 'root'@'localhost'。它不依赖密码,靠 Unix socket 文件校验系统用户身份。若需密码登录(比如远程连接或某些客户端工具),必须先切认证方式:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_strong_password';
检查过期但未锁死的账号:密码存在但长期未更新
MySQL 支持密码过期策略,但默认不启用。如果启用了(如通过 default_password_lifetime = 180),可用以下语句找出密码已超期却仍可登录的账号(即 account_locked = 'N'):
SELECT user, host, password_last_changed, account_locked FROM mysql.user WHERE password_last_changed IS NOT NULL AND DATE_SUB(NOW(), INTERVAL 180 DAY) > password_last_changed AND account_locked = 'N';
这个查询依赖实际配置的过期天数,别硬套 180;生产环境建议结合 SHOW VARIABLES LIKE 'default_password_lifetime'; 确认当前阈值。
为什么 SELECT user, password FROM mysql.user 在 8.0+ 会报错?
因为 MySQL 8.0 彻底移除了 password 字段。如果你在 8.0+ 环境下执行老式查询,会收到 ERROR 1054 (42S22): Unknown column 'password' in 'field list'。必须改用 authentication_string。另外,即使字段名对了,也别指望看到明文或可逆哈希——它存的是不可逆的 SHA256 hash(mysql_native_password)或插件特定凭证,和操作系统密码存储逻辑一致:只用于比对,不用于还原。











