mysql测试账户禁用固定密码,因其易被窃取、助长横向渗透且无法审计;应通过事件调度器自动轮换密码,客户端改用login-path等安全方式获取凭据,并统一使用alter user更新密码以确保兼容性与安全性。

MySQL测试账户为什么不能长期用固定密码
测试环境看似不重要,但常被当成跳板:开发连错库、CI/CD凭据硬编码、自动化脚本明文存密码——mysql -u testuser -p输一次,就可能被进程快照或命令历史捕获。更麻烦的是,一旦某台开发机失陷,攻击者能靠这个账户横向扫其他测试实例。固定密码还意味着无法追溯“谁在什么时候用了这个账号”,审计日志里全是 testuser@192.168.5.%,没意义。
- 密码生命周期必须可控,不能依赖人工定期改
- 账户权限要最小化,禁用
DROP、CREATE USER 等高危操作
- 避免使用
root 或同名生产账户复用测试环境
用MySQL事件调度器自动轮换密码
MySQL 5.7+ 自带事件调度器(Event Scheduler),比外部 cron + mysqladmin 更可靠:不依赖 shell 环境、不暴露密码到进程参数、执行上下文统一。关键是得关掉 log_bin_trust_function_creators 否则事件创建会失败,且事件本身要用 DEFINER 显式指定高权限账户(如 dba@localhost)。
- 确保
event_scheduler=ON(查 SHOW VARIABLES LIKE 'event_scheduler';)
- 创建事件前先建一个安全的密码生成函数(避免用
RAND() 直接拼接,易预测)
- 事件 SQL 中禁止写明文密码,改用
SET PASSWORD FOR 'testuser'@'%' = SHA2('新密码',256); 这类语句
- 事件定义里加
ON COMPLETION PRESERVE ENABLE,防止误删后失效
CREATE EVENT rotate_testuser_password
ON SCHEDULE EVERY 7 DAY
DO
BEGIN
SET @newpass = CONCAT('tst_', SUBSTRING(SHA2(RAND(),256), 1, 12));
SET @sql = CONCAT("ALTER USER 'testuser'@'%' IDENTIFIED BY '", @newpass, "'");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
客户端连接时怎么不硬编码密码
开发和CI脚本如果还写 mysql -u testuser -p'abc123',定时改密码等于白做。得让客户端主动拉取最新凭据,而不是反向去适配密码变更。
- 开发机统一用
~/.my.cnf,但配置段落设为 [testenv],连接时显式指定 mysql --defaults-group-suffix=testenv
- CI/CD 中禁用
MYSQL_PWD 环境变量(它会被 ps 看见),改用 mysql_config_editor 存加密登录路径:mysql_config_editor set --login-path=testenv --user=testuser --host=localhost
- 所有脚本连接都加
--login-path=testenv,这样密码更新后只需重跑一次 mysql_config_editor set 即可
为什么 ALTER USER 比 SET PASSWORD 更稳妥SET PASSWORD 在 MySQL 8.0.11+ 已标记为过时,且对 caching_sha2_password 插件支持不稳定;而 ALTER USER ... IDENTIFIED BY 是当前唯一保证兼容所有认证插件的方式。更重要的是,ALTER USER 会清空该账户的密码历史缓存(如果启用了 password_history),避免新密码撞上旧记录被拒绝。
- 不要用
UPDATE mysql.user 直接改表,会导致权限缓存不刷新,必须跟 FLUSH PRIVILEGES,但该命令在某些版本有并发 bug
- 如果测试账户启用了
password_reuse_interval,ALTER USER 会自动绕过限制(只要不是完全重复)
- 注意:MySQL 8.0 默认认证插件是
caching_sha2_password,旧版客户端(如 MySQL 5.7 客户端)连不上,得在创建用户时显式指定 IDENTIFIED WITH mysql_native_password
DROP、CREATE USER 等高危操作 root 或同名生产账户复用测试环境 mysqladmin 更可靠:不依赖 shell 环境、不暴露密码到进程参数、执行上下文统一。关键是得关掉 log_bin_trust_function_creators 否则事件创建会失败,且事件本身要用 DEFINER 显式指定高权限账户(如 dba@localhost)。
- 确保
event_scheduler=ON(查SHOW VARIABLES LIKE 'event_scheduler';) - 创建事件前先建一个安全的密码生成函数(避免用
RAND()直接拼接,易预测) - 事件 SQL 中禁止写明文密码,改用
SET PASSWORD FOR 'testuser'@'%' = SHA2('新密码',256);这类语句 - 事件定义里加
ON COMPLETION PRESERVE ENABLE,防止误删后失效
CREATE EVENT rotate_testuser_password
ON SCHEDULE EVERY 7 DAY
DO
BEGIN
SET @newpass = CONCAT('tst_', SUBSTRING(SHA2(RAND(),256), 1, 12));
SET @sql = CONCAT("ALTER USER 'testuser'@'%' IDENTIFIED BY '", @newpass, "'");
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
客户端连接时怎么不硬编码密码
开发和CI脚本如果还写 mysql -u testuser -p'abc123',定时改密码等于白做。得让客户端主动拉取最新凭据,而不是反向去适配密码变更。
- 开发机统一用
~/.my.cnf,但配置段落设为 [testenv],连接时显式指定 mysql --defaults-group-suffix=testenv
- CI/CD 中禁用
MYSQL_PWD 环境变量(它会被 ps 看见),改用 mysql_config_editor 存加密登录路径:mysql_config_editor set --login-path=testenv --user=testuser --host=localhost
- 所有脚本连接都加
--login-path=testenv,这样密码更新后只需重跑一次 mysql_config_editor set 即可
为什么 ALTER USER 比 SET PASSWORD 更稳妥SET PASSWORD 在 MySQL 8.0.11+ 已标记为过时,且对 caching_sha2_password 插件支持不稳定;而 ALTER USER ... IDENTIFIED BY 是当前唯一保证兼容所有认证插件的方式。更重要的是,ALTER USER 会清空该账户的密码历史缓存(如果启用了 password_history),避免新密码撞上旧记录被拒绝。
- 不要用
UPDATE mysql.user 直接改表,会导致权限缓存不刷新,必须跟 FLUSH PRIVILEGES,但该命令在某些版本有并发 bug
- 如果测试账户启用了
password_reuse_interval,ALTER USER 会自动绕过限制(只要不是完全重复)
- 注意:MySQL 8.0 默认认证插件是
caching_sha2_password,旧版客户端(如 MySQL 5.7 客户端)连不上,得在创建用户时显式指定 IDENTIFIED WITH mysql_native_password
~/.my.cnf,但配置段落设为 [testenv],连接时显式指定 mysql --defaults-group-suffix=testenv MYSQL_PWD 环境变量(它会被 ps 看见),改用 mysql_config_editor 存加密登录路径:mysql_config_editor set --login-path=testenv --user=testuser --host=localhost --login-path=testenv,这样密码更新后只需重跑一次 mysql_config_editor set 即可 SET PASSWORD 在 MySQL 8.0.11+ 已标记为过时,且对 caching_sha2_password 插件支持不稳定;而 ALTER USER ... IDENTIFIED BY 是当前唯一保证兼容所有认证插件的方式。更重要的是,ALTER USER 会清空该账户的密码历史缓存(如果启用了 password_history),避免新密码撞上旧记录被拒绝。
- 不要用
UPDATE mysql.user直接改表,会导致权限缓存不刷新,必须跟FLUSH PRIVILEGES,但该命令在某些版本有并发 bug - 如果测试账户启用了
password_reuse_interval,ALTER USER会自动绕过限制(只要不是完全重复) - 注意:MySQL 8.0 默认认证插件是
caching_sha2_password,旧版客户端(如 MySQL 5.7 客户端)连不上,得在创建用户时显式指定IDENTIFIED WITH mysql_native_password
密码轮换本身不难,难的是让所有接入点同步感知变更——配置中心、连接池、IDE 数据源设置、Docker Compose 的 MYSQL_PASSWORD,每个漏掉一处,就会出现“密码已更新但某处还在连老密码”的静默故障。











