PostgreSQL中仅授SELECT权限仍可见其他表,因public schema默认可读且系统目录暴露;须撤销PUBLIC对public的USAGE、显式授权目标schema和表,并可选禁用pg_catalog访问。
PostgreSQL 中只给 SELECT 权限到单张表,但用户仍能 pg_catalog 查到其他表?
默认开启的 public schema 可读权限和系统目录暴露是主因。postgresql 不会因为“没给某张表权限”就自动隐藏它——只要用户能连上数据库、有 usage 权限到 schema,就能通过 pg_tables、information_schema.tables 看到所有表名。
实操建议:
- 撤销
publicschema 的默认USAGE权限:REVOKE USAGE ON SCHEMA public FROM PUBLIC;
- 只为该用户显式授予目标 schema 的
USAGE:GRANT USAGE ON SCHEMA my_secure_schema TO limited_user;
- 只授予目标表的
SELECT:GRANT SELECT ON TABLE my_secure_schema.sensitive_data TO limited_user;
- 禁用对系统目录的普通访问(可选但推荐):
REVOKE SELECT ON TABLE pg_catalog.pg_tables FROM PUBLIC;
(注意:这会影响部分客户端工具的自动补全,但不影响 SQL 执行)
MySQL 8.0+ 用 CREATE VIEW 包一层表,再授予权限是否安全?
不完全安全——视图本身不隔离元数据,用户仍可通过 SHOW TABLES 或 INFORMATION_SCHEMA 看到原始表名,除非你同时限制 schema 级别访问。
更稳妥的做法是结合 SQL SECURITY DEFINER + 精确权限控制:
- 创建视图时指定
SQL SECURITY DEFINER,并由高权限账号拥有:CREATE DEFINER = 'admin'@'localhost' SQL SECURITY DEFINER VIEW v_sensitive AS SELECT id, name FROM real_table;
- 仅授予用户对视图的
SELECT,且确保其对原表、原 schema 都无任何权限:GRANT SELECT ON mydb.v_sensitive TO 'limited'@'%'; REVOKE ALL PRIVILEGES ON mydb.real_table FROM 'limited'@'%';
- 关闭
information_schema的冗余暴露(MySQL 8.0+):SET PERSIST information_schema_stats_expiry = 0;
并确认show_compatibility_56 = OFF,避免旧接口泄露
Oracle 中用 READ 对象权限代替 SELECT,真能防字段级探测?
不能。READ 是 Oracle 12c 引入的简化权限,语义等价于 SELECT,不提供额外遮蔽能力。用户仍可通过 DESCRIBE 或查询 ALL_TAB_COLUMNS 获取字段名和类型。
若需真正隐藏结构,必须配合数据字典权限管控:
- 回收用户对
ALL_*视图的SELECT权限:REVOKE SELECT ON ALL_TAB_COLUMNS FROM limited_user;
- 仅保留其对
USER_TAB_COLUMNS的访问(该视图只返回用户自己拥有的对象); - 确保目标表不在
limited_user拥有的 schema 下(否则USER_*视图仍会暴露); - 必要时启用 Oracle Data Redaction 或 Virtual Private Database(VPD),但这是行级/列级控制,非权限层方案
所有数据库共通的「权限幻觉」陷阱:连接后第一句 SELECT 1 成功 ≠ 表级权限已生效
很多用户误以为能连库、能执行简单语句,就代表权限配置完成。实际上,权限检查发生在对象访问时刻,而非连接或语法解析阶段。一个典型失败场景是:用户能连上,也能 SELECT 1,但一查目标表就报 permission denied for table xxx —— 往往是因为漏了 USAGE on schema(PostgreSQL)、SELECT on table(MySQL)、或未刷新权限缓存(MySQL FLUSH PRIVILEGES)。
排查顺序建议:
- 确认用户是否具备目标 schema 的
USAGE(PG)或 database 的USAGE(MySQL); - 确认表名是否带 schema 前缀(省略时依赖
search_path或默认 database); - MySQL 用户注意:修改权限后必须执行
FLUSH PRIVILEGES,否则新权限不加载; - PostgreSQL 用户注意:
REVOKE操作不会级联,若之前通过角色继承获得权限,需从源头角色撤销
最易被忽略的是 schema 层权限——它像一道门,表权限只是门上的锁。门没关严,锁再牢也没用。










