测试环境权限模型不可直接复用生产环境,需按内网ip段精确授权、禁用通配符host、适配caching_sha2_password认证插件并显式配置require ssl,权限回收须先revoke再drop user。

直接复用生产环境的权限模型到测试环境,不仅没必要,反而会放大风险——测试库本就允许建表、删表、清空数据,若照搬生产账号的 SELECT,INSERT,UPDATE,DELETE 限制,反而会让开发连 DROP TABLE 都执行不了,卡在本地验证环节。
测试环境用户必须绑定内网IP段,不能用'%'@'%'
生产环境常把应用账号限定在 'app_user'@'192.168.10.%' 这类内网段,但测试环境容易图省事写成 'test_user'@'%'。这会导致:本地IDE、CI/CD节点、甚至同事笔记本都能连上测试库,一旦密码泄露或配置误提交,测试数据可能被意外导出或篡改。
- 正确做法是按实际接入方划分:开发机用
'dev_user'@'10.0.1.0/24',CI服务器用'ci_user'@'172.20.5.10',明确到单IP或子网 - 避免用
localhost做主机名——Docker容器或远程SSH端口转发时,localhost指的是容器内部,不是宿主机,连接会直接拒绝 - 执行后务必用
SELECT user,host FROM mysql.user WHERE user='test_user';确认记录已写入,MySQL不支持通配符模糊匹配host字段
GRANT语句里别漏掉REQUIRE SSL(即使测试环境没配证书)
MySQL 8.0+ 默认认证插件是 caching_sha2_password,它要求TLS握手。如果你在测试环境没配SSL证书,又没显式禁用,客户端(比如某些版本的 mysql-connector-python 或旧版Navicat)会静默降级失败,报错 Access denied for user,但实际是握手阶段被拦,不是权限问题。
- 安全且兼容的做法是加
REQUIRE SSL,然后在MySQL配置中设置ssl-mode=DISABLED(客户端侧)或临时关闭服务端强制要求(仅限可信内网) - 更稳妥的是统一用
mysql_native_password插件:执行ALTER USER 'test_user'@'10.0.1.%' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 验证是否生效:用该账号登录后运行
SELECT Ssl_cipher FROM performance_schema.session_status WHERE Variable_name = 'Ssl_cipher';,返回空值表示未启用SSL,非空则说明已协商成功
权限回收必须分两步:REVOKE + DROP USER
只执行 REVOKE ALL PRIVILEGES ON *.* FROM 'test_user'@'%'; 并不能真正删除账号——mysql.user 表里记录还在,下次有人误执行 GRANT 就会复活权限,且表级、列级权限(如果设过)根本不受影响。
- 标准清理流程是:
REVOKE ALL PRIVILEGES ON *.* FROM 'test_user'@'10.0.1.%';→DROP USER 'test_user'@'10.0.1.%'; - 注意:MySQL不允许对不存在的用户执行
DROP USER,所以先查SELECT User,Host FROM mysql.user WHERE User='test_user';再操作 - 批量清理时,别用
DROP USER 'test_user'@'%';试图一网打尽——它只删host为%的那条,而你实际创建的是'test_user'@'10.0.1.%',两者不匹配
权限模型不是复制粘贴就能迁移的,测试环境的核心矛盾在于:既要模拟生产访问逻辑(比如同名账号、同粒度权限),又要保留调试自由度(比如允许 TRUNCATE、CREATE TEMPORARY TABLE)。最容易被忽略的是 host 匹配精度和认证插件兼容性,这两点不处理好,连最基础的连接都会失败,根本谈不上权限一致性。











