mysql中基于IP地址的访问控制与权限配置

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

MySQL 用户账号的 host 字段决定 IP 访问范围

MySQL 权限系统里,

user
表中的
host
列不是辅助字段,而是访问控制的核心判断依据。同一个用户名(如
'app'
),搭配不同
host
值,会被视为完全独立的账号:
'app'@'192.168.1.100'
'app'@'192.168.1.%'
互不影响,权限需分别授予。

常见误区是以为只创建

'app'@'%'
就能覆盖所有场景——这会开放任意 IP 连接,且无法对内网、外网做差异化策略。

'app'@'localhost'
:仅允许本机 Unix socket 或 127.0.0.1 TCP 连接,不走网络栈
'app'@'192.168.1.5'
:精确匹配单个 IPv4 地址
'app'@'192.168.1.%'
:匹配该 C 类网段全部 IPv4(注意:不匹配 IPv6)
'app'@'%.example.com'
:支持域名通配,但依赖 MySQL 的 DNS 反查(不推荐,性能差且不可靠)

GRANT 语句必须显式指定 host,不能省略

执行

GRANT
时若漏写
host
,MySQL 默认补为
'%'
,这是高危默认行为。例如:
GRANT SELECT ON db.* TO 'report' IDENTIFIED BY 'pwd';
实际创建的是
'report'@'%'
,而非你预期的本地账号。

正确写法必须带引号并明确 host:

GRANT SELECT ON sales.* TO 'report'@'10.0.20.0/24' IDENTIFIED BY 'R3p0rt!2024';
GRANT INSERT, UPDATE ON orders.* TO 'api'@'172.16.5.10' IDENTIFIED BY 'ApiPass#1';

注意:

'10.0.20.0/24'
是 MySQL 8.0+ 支持的 CIDR 语法;低版本只能用
'10.0.20.%'
模拟,但无法精确排除
10.0.20.255
这类地址。

防火墙与 bind-address 会先于 MySQL 权限生效

MySQL 的

host
匹配只发生在 TCP 连接已建立之后。如果连接根本连不上,问题大概率出在更底层:

bind-address
my.cnf
中设为
127.0.0.1
,则 MySQL 只监听本地回环,外部 IP 无法建立 TCP 连接
Linux
iptables
nftables
未放行 3306 端口,SYN 包被丢弃,客户端超时
云平台安全组(如 AWS Security Group、阿里云 ECS 安全组)未配置入向规则,流量在宿主机前就被拦截

验证顺序建议:先用

telnet 192.168.1.10 3306
看端口是否可达;再确认
SELECT user, host FROM mysql.user;
中对应账号是否存在且
host
匹配;最后检查
SHOW GRANTS FOR 'user'@'host';
是否包含所需权限。

REVOKE 和 DROP USER 不清理残留权限缓存

执行

DROP USER 'old'@'192.168.5.%';
后,如果之前存在
'old'@'%'
账号,它仍有效;同理,
REVOKE
不会自动刷新权限表缓存。

必须手动触发重载:

FLUSH PRIVILEGES;

否则新授权或删除操作不会立即生效。这个命令虽快,但它是全局锁,高并发写入期间可能短暂阻塞其他 DDL 操作。生产环境建议在低峰期执行,或改用 MySQL 8.0+ 的

ALTER USER ... REQUIRE NONE
配合证书限制,减少对
FLUSH PRIVILEGES
的依赖。

CIDR 写法、

bind-address
配置、
FLUSH PRIVILEGES
的必要性——这三个点最容易在排查时被跳过,结果花两小时查权限,实际是防火墙没开或者配置文件没重载。

相关推荐