MySQL用户host字段需填具体网段通配符(如'192.168.5.%')才生效,不能用'%'或'localhost';必须CREATE USER与GRANT中host完全一致,并执行FLUSH PRIVILEGES。

MySQL用户host字段到底填什么才生效
MySQL的用户权限是靠 user@host 这个组合唯一标识的,不是只看用户名。所谓“限制从指定网段登录”,本质就是把 host 部分设为对应网段的通配形式,而不是用 '%' 或 'localhost' 这类宽泛值。
常见错误是执行了 CREATE USER 'foo'@'%' IDENTIFIED BY 'pwd';,结果发现任何IP都能连——因为 '%' 匹配所有主机(包括远程),且不区分网段。
-
'192.168.1.%'匹配 192.168.1.0/24 网段(注意:点号是字面量,不能省略) -
'10.0.0.0/255.255.255.0'是无效写法——MySQL原生不支持CIDR语法 -
'172.16.0.0/12'同样不被识别,必须拆成多个'172.16.%'、'172.17.%'…或用更粗粒度的掩码 - IPv6需用方括号,如
'user'@'2001:db8::/32'仍不支持,只能写'user'@'2001:db8::%'(匹配前缀)
创建网段受限用户的具体步骤
不能只靠 CREATE USER,必须配合 GRANT 显式授权,且 host 必须完全一致。MySQL 8.0+ 还要留意默认认证插件变化。
以限制用户 app_rw 只能从 192.168.5.0/24 登录为例:
CREATE USER 'app_rw'@'192.168.5.%' IDENTIFIED WITH mysql_native_password BY 'strong-pass-2024'; GRANT SELECT, INSERT, UPDATE ON mydb.* TO 'app_rw'@'192.168.5.%'; FLUSH PRIVILEGES;
- 如果用的是 MySQL 8.0+ 且服务端配置了
default_authentication_plugin = caching_sha2_password,客户端不支持该插件时会连不上,此时显式指定IDENTIFIED WITH mysql_native_password更稳妥 -
GRANT的ON子句可以是库级或表级,但TO后的用户host必须和CREATE USER中的一致,否则权限不生效 - 执行完务必运行
FLUSH PRIVILEGES;,尤其在直接操作mysql.user表后
验证是否真被限制住了
别只信自己写的SQL,要用真实连接测试。最容易忽略的是:MySQL优先匹配最具体的host规则,且大小写不敏感但字符必须精确。
- 从允许网段外的机器执行
mysql -u app_rw -p -h your-mysql-host,应报错Access denied for user 'app_rw'@'192.168.8.23'(末尾IP是实际来源) - 检查当前生效的用户记录:
SELECT User, Host FROM mysql.user WHERE User = 'app_rw';,确认只有'192.168.5.%'这一条(避免残留'%'记录) - 注意DNS反解影响:如果MySQL配置了
skip_name_resolve = OFF(默认),它会尝试把客户端IP反向解析成域名,再匹配Host字段——这时'192.168.5.%'可能不命中,建议始终开启skip_name_resolve = ON
批量限制多个网段或避免手误
一个用户要允许多个网段?不要堆砌一堆 'app_rw'@'x.x.x.%' 用户——管理成本高,且权限分散难审计。更可靠的做法是用跳板机或代理层收敛出口IP,或者借助防火墙先过滤。
- 若真需多网段,逐条创建并授权:
CREATE USER 'app_rw'@'10.20.30.%'...+ 对应GRANT,每条都独立存在 - 删除错误用户用
DROP USER 'app_rw'@'%';,别用DELETE FROM mysql.user直接删行,否则权限系统可能不一致 - 生产环境改权限前,先在测试库用
SHOW GRANTS FOR 'app_rw'@'192.168.5.%';确认当前策略
网段限制看似简单,真正卡住人的往往是 host 字符串的细节匹配逻辑、DNS解析干扰、以及旧权限残留。动手前先查 mysql.user 里到底存了什么,比反复试错快得多。


















