只授GRANT SELECT ON db_name.*仍会泄露元数据,因MySQL默认允许已认证用户执行SHOW DATABASES及查询information_schema.TABLES、COLUMNS等视图,第三方工具连接后自动探测导致库名、表结构、字段注释等全部暴露。

直接给第三方系统开一个 SELECT 权限账号,90% 的情况下会暴露库名、表结构、字段注释甚至索引信息——这不是权限配窄了,是边界根本没划清。
为什么只授 GRANT SELECT ON db_name.* 还会泄露元数据?
MySQL 默认允许已认证用户执行 SHOW DATABASES 和查询 information_schema.TABLES、information_schema.COLUMNS。第三方工具(如 Power BI、DBeaver、自研同步服务)一连接就会自动查这些视图来渲染字段列表或生成 SQL,结果你只给了业务库 SELECT,它却把整个数据库骨架都“看”全了。
-
SHOW DATABASES返回所有库名 → 暴露未授权库的存在 -
SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'xxx'→ 可枚举所有表名及行数 -
SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT FROM information_schema.COLUMNS→ 拿到字段类型、长度、注释,甚至敏感字段命名逻辑
用视图封装 + 显式授权切断元数据链
真正可控的方式,是让第三方**不需要查元数据**——提前把需要的数据投影成视图,只授这个视图的 SELECT,并禁掉所有其他入口。
- 视图必须在目标库下创建,例如:
CREATE VIEW `reporting_vw_orders` AS SELECT id, order_no, status FROM sales_db.orders WHERE status IN ('paid', 'shipped'); - 显式撤销原表权限:
REVOKE SELECT ON sales_db.orders FROM 'api_user'@'192.168.10.%'; - 只授视图权限:
GRANT SELECT ON sales_db.reporting_vw_orders TO 'api_user'@'192.168.10.%'; - 视图必须声明
SQL SECURITY DEFINER,否则运行时会以调用者身份检查底层表权限,导致报错
必须补的三项最小化授权
即使用了视图,多数 API 客户端或 ORM 仍会尝试查元数据来适配类型。但绝不能开 INFORMATION_SCHEMA.*,只需三张表的 SELECT:
-
GRANT SELECT ON information_schema.COLUMNS TO 'api_user'@'192.168.10.%';(几乎所有工具都依赖,用于识别字段类型) -
GRANT SELECT ON information_schema.TABLES TO 'api_user'@'192.168.10.%';(若需自动发现视图名,否则可省略) -
GRANT SELECT ON information_schema.STATISTICS TO 'api_user'@'192.168.10.%';(仅当工具要读索引信息才加,一般不用) - 务必执行:
REVOKE SHOW DATABASES ON *.* FROM 'api_user'@'192.168.10.%';,否则SHOW DATABASES仍返回全部库名
认证与连接层硬约束不能少
视图和权限再严,挡不住暴力连或长期凭证滥用。必须配套限制:
- 创建用户时绑定 IP 段:
CREATE USER 'api_user'@'192.168.10.%' IDENTIFIED WITH mysql_native_password BY 'xxx';(MySQL 8.0+ 必须指定插件,否则老客户端连不上) - 强制密码轮换:
ALTER USER 'api_user'@'192.168.10.%' PASSWORD EXPIRE INTERVAL 30 DAY; - 限制并发连接:
ALTER USER 'api_user'@'192.168.10.%' WITH MAX_USER_CONNECTIONS 5; - 验证时用
SELECT USER(), CURRENT_USER();确认匹配的是api_user@192.168.10.x,不是通配符api_user@'%'覆盖了
最易被忽略的一点:MySQL 8.0+ 的角色机制虽好,但第三方工具通常不支持 SET ROLE,所以别用角色封装权限——直接授给用户更可靠。另外,任何 FLUSH PRIVILEGES 都不是必需操作,除非你手动改过 mysql.user 表;常规 GRANT 后权限立即生效。


















