mysql中创建用户时限制IP与主机访问权限

来源:这里教程网 时间:2026-02-28 20:40:41 作者:

MySQL 创建用户时如何指定允许连接的 IP 或主机名

MySQL 用户名由

'user'@'host'
两部分组成,其中
host
部分直接决定该用户能从哪些客户端发起连接。它不是“额外配置项”,而是创建用户时必须显式声明的核心组成部分。

常见误区是先用

CREATE USER 'u1'@'localhost'
创建,再试图用
GRANT ... ON *.* TO 'u1'
改权限——这不会改变
host
值,只会报错或静默失败。

'localhost'
:仅允许本机 Unix socket 或 127.0.0.1(取决于 MySQL 配置),不等价于
'127.0.0.1'
(后者走 TCP)
'192.168.1.100'
:只允许来自该 IP 的 TCP 连接
'192.168.1.%'
:匹配 192.168.1 网段所有 IPv4 地址(注意:不匹配 IPv6)
'%.example.com'
:匹配所有以
.example.com
结尾的主机名(需 DNS 可解析)
'%'
:允许任意主机连接(含公网),生产环境应避免

使用 CREATE USER 时必须写全 host 部分

不能省略

@'host'
,也不能只写用户名。MySQL 5.7+ 默认不允许空 host,且
CREATE USER 'u1'
会被解释为
'u1'@'%'
,这是高危行为。

正确写法示例:

CREATE USER 'app_user'@'10.20.30.40' IDENTIFIED BY 's3cur3_p@ss';

如果想允许多个固定 IP,需分别创建多个用户(MySQL 不支持单用户绑定多个 host):

CREATE USER 'app_user'@'10.20.30.40' IDENTIFIED BY 's3cur3_p@ss';
CREATE USER 'app_user'@'10.20.30.41' IDENTIFIED BY 's3cur3_p@ss';

注意:

IDENTIFIED BY
在 MySQL 8.0+ 中仍有效,但推荐用
IDENTIFIED WITH caching_sha2_password BY '...'
显式指定认证插件。

GRANT 语句中的 host 必须与 CREATE USER 一致

GRANT
不会修改用户定义的 host,它只是给某个已存在的
'user'@'host'
授权。若执行:

CREATE USER 'api'@'192.168.5.0/24';
GRANT SELECT ON mydb.* TO 'api'@'%';

第二行会报错:

ERROR 1396 (HY000): Operation GRANT failed for 'api'@'%'
,因为用户实际是
'api'@'192.168.5.0/24'
(MySQL 8.0+ 支持 CIDR 写法,但仍是完整 host 字符串)。

正确做法是:

CREATE USER 'api'@'192.168.5.0/24' IDENTIFIED BY 'p@ss';
GRANT SELECT ON mydb.* TO 'api'@'192.168.5.0/24';

另外,

host
匹配是**精确字符串匹配**,不支持通配符嵌套(如
'192.168.*.100'
无效)。

验证用户 host 是否生效及常见连不上原因

连不上最常被忽略的是:MySQL 服务是否监听了对应网卡、防火墙是否放行 3306 端口、客户端是否用了正确的 host 参数(例如用

mysql -h 127.0.0.1 -u u1
mysql -h localhost -u u1
可能命中不同用户)。

检查当前所有用户及其 host:

SELECT User, Host FROM mysql.user;

查看某用户具体权限(确认 host 完全一致):

SHOW GRANTS FOR 'webapp'@'172.16.0.5';

特别注意:MySQL 8.0+ 默认启用

skip_name_resolve = ON
,此时 host 部分不会做 DNS 反查,
'user'@'host.example.com'
只匹配客户端 TCP 连接时声明的 hostname(通常不可靠),建议一律用 IP 或
'%'
+ 网络层控制。

host 字符串一旦写错(比如多一个空格、大小写不一致、用了中文引号),用户就无法匹配,且错误提示往往模糊(如

Access denied for user
),排查时务必逐字符核对
User
Host
输出结果。

相关推荐