如何隐藏数据库中的特定表不让用户看到_剥离权限与Schema逻辑隔离

1次阅读

REVOKE 权限需同时撤销表级 SELECT 及 schema 级 USAGE 才能彻底隐藏表名,否则 dt 仍可见;VIEW 须用 SQL SECURITY DEFINER 且避免敏感字段;SQL Server 须用 sys.fn_my_permissions 验证权限是否真正剥离。

如何隐藏数据库中的特定表不让用户看到_剥离权限与 Schema 逻辑隔离

PostgreSQL 中用 REVOKE 剥离用户对特定表的 SELECT 权限

直接撤掉权限是最常见也最有效的隐藏方式,但很多人只撤了 SELECT,忘了 USAGESELECT 在 schema 层的组合效应。用户仍可能通过 dtpg_tables 看到表名——因为表名本身不依赖行级权限,而取决于 schema 的 USAGE

  • 先确认目标用户当前拥有的权限:SELECT grantee, privilege_type FROM information_schema.role_table_grants WHERE table_name = 'sensitive_table';
  • 撤销核心权限(缺一不可):REVOKE SELECT ON TABLE sensitive_table FROM app_user; + REVOKE INSERT, UPDATE, DELETE ON TABLE sensitive_table FROM app_user;
  • 如果用户不需要访问整个 schema,顺手收回 schema 级 USAGEREVOKE USAGE ON SCHEMA public FROM app_user;(否则 dt 仍会列出所有表)
  • 注意:REVOKE 不会级联,父 role 的权限不会自动失效;若用户是通过 group role 获得权限,需在 group 上操作或用 REASSIGN OWNED 配合 DROP OWNED

MySQL 8.0+ 用 CREATE VIEW 替代直接暴露原表

物理隐藏不如逻辑隔离可靠——尤其当 DBA 无法控制应用连接账号时,VIEW 是更可控的出口。但别把 VIEW 当权限开关:用户只要对 VIEW 有 SELECT,就默认能查,和底层表权限无关;真正起作用的是建 VIEW 时用的 SQL SECURITY DEFINER

  • 创建带安全上下文的 VIEW:CREATE VIEW safe_user_list AS SELECT id, name, created_at FROM users WHERE status = 'active' SQL SECURITY DEFINER;
  • SQL SECURITY DEFINER 表示执行时以定义者(通常是 DBA)身份校验权限,用户无需对原表有权限
  • 务必避免在 VIEW 定义中引用敏感字段(如 password_hash),且不要用 UNION 拼接不同权限级别的表——MySQL 会校验所有分支的权限
  • 测试时用目标用户登录后执行:SELECT * FROM safe_user_list;,再尝试 SELECT * FROM users; 确认报错 ERROR 1142 (42000): SELECT command denied to user

SQL Server 中 sys.fn_my_permissions 检查权限是否真被剥离

光跑 REVOKE 不等于权限消失,SQL Server 的权限继承链复杂(database → schema → object → column),常出现“以为撤了,其实还能查”的情况。必须用系统函数验证最终效果。

  • 切换到目标用户上下文后运行:SELECT * FROM sys.fn_my_permissions('sensitive_table', 'OBJECT');
  • 结果为空 = 真没权限;若仍有 SELECT,说明权限来自更高层(比如 schema 的 db_datareader 角色),得去角色里查
  • 检查角色继承:SELECT r.name AS role_name, m.name AS member_name FROM sys.database_role_members rm JOIN sys.database_principals r ON rm.role_principal_id = r.principal_id JOIN sys.database_principals m ON rm.member_principal_id = m.principal_id WHERE m.name = 'app_user';
  • 别忽略列级权限:即使表级 SELECT 被撤,GRANT SELECT ON sensitive_table(password_hash) TO app_user; 仍会让某列可读

Schema 隔离不是权限替代方案,而是补充手段

把敏感表挪到 private schema 并收回该 schema 的 USAGE,确实能让 information_schema.tables 查不到——但这只是藏名字,不是藏数据。一旦用户知道表存在,且 schema 名泄露(比如日志、错误消息、开发环境残留),权限缺失就形同虚设。

  • schema 隔离适合配合权限使用:先 CREATE SCHEMA private;,再 ALTER TABLE users SET SCHEMA private;,最后 REVOKE USAGE ON SCHEMA private FROM PUBLIC;
  • PostgreSQL 中,pg_tables 默认只查 current_schemas(false) 包含的 schema;但 SELECT * FROM pg_class WHERE relname = 'users' 仍可见,因为这是 catalog 级查询
  • MySQL 和 SQL Server 没有真正的 schema 隔离概念(MySQL 的 database ≈ schema,SQL Server 的 schema 更像命名空间),强行类比容易误判
  • 最易被忽略的一点:应用 ORM(如 Django、Hibernate)常自动生成 INFORMATION_SCHEMA 查询来推断结构,这类查询走的是连接用户的权限,不是应用代码的逻辑权限
星耀云
版权声明:本站原创文章,由 星耀云 2026-03-22发表,共计2334字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources