oracle中“隐藏表”本质是权限隔离,需同时撤销对象select权限、相关字典角色(如select_catalog_role)及引用对象权限,并推荐用应用角色替代直接授权以实现按需启用。
oracle 中“隐藏表”不等于删表或加密,本质是权限隔离
oracle 没有原生的 hide table 语法,所谓“隐藏特定 schema 的表”,真实含义是:让某用户(尤其是应用账号)在连接后 既查不到表名,也访问不了数据。关键不是藏表,而是切断发现路径和访问链路。常见错误是只撤 select 权限,结果用户仍能通过 select * from all_tables 或 navicat 的对象树看到表名——因为表名可见性取决于 schema 级 select_catalog_role 或 select any dictionary,而非单表权限。
必须同时撤销三类权限才能真正“不可见”
以用户 app_user 为例,要让 hr.employees 在其会话中彻底消失(\dt 类效果),需执行:
-
REVOKE SELECT ON hr.employees FROM app_user;(撤数据读取) -
REVOKE SELECT ON hr.departments FROM app_user;(若该表被视图/约束引用,也得一并撤) -
REVOKE SELECT_CATALOG_ROLE FROM app_user;(关键!否则ALL_TABLES仍可查)
注意:SELECT_CATALOG_ROLE 是高危角色,常被误授。它等价于允许用户遍历整个数据字典。若应用真不需要查元数据,直接回收比加白名单更安全。验证方式:用 app_user 登录后执行 SELECT table_name FROM all_tables WHERE owner = 'HR';,应返回空集且无报错(权限不足不报错,只不返回)。
用应用角色(Application Role)替代直接授权,避免权限泄露
直接给 app_user 授 SELECT 是静态、粗粒度的。换成应用角色,可实现“按需启用”:
- 创建角色:
CREATE ROLE app_hr_reader; - 只授必要表:
GRANT SELECT ON hr.employees TO app_hr_reader; - 不授任何字典权限:绝不执行
GRANT SELECT_CATALOG_ROLE TO app_hr_reader; - 登录后激活:
SET ROLE app_hr_reader;(需提前GRANT app_hr_reader TO app_user;)
这样,app_user 默认无任何 HR 表权限,连 DESCRIBE hr.employees 都失败;只有显式 SET ROLE 后才获得有限访问能力。比单纯 REVOKE 更可控,也防止开发误写 SELECT * FROM ALL_TABLES 泄露结构。
Navicat 连接 Oracle 时“隐藏其他 Schema”的实操限制
Navicat 的「模式过滤」只是客户端显示控制,不改变服务端权限。你在连接属性里填 HR,FINANCE,只是让它不展开其他 Schema 的树节点,但用户只要执行 SELECT * FROM scott.emp;,只要权限存在,照样能查。所以:
- 先确保服务端权限已收紧(按前两节操作)
- 再在 Navicat 中右键连接 → 编辑连接 → 「高级」→「模式筛选」输入大写 Schema 名,逗号分隔(如
HR,FINANCE) - 刷新连接后,未列出的 Schema 不会在左侧对象树出现,但 SQL 执行不受限
真正容易被忽略的是:Oracle 的 Schema 和用户同名,SELECT_CATALOG_ROLE 的默认授予行为极隐蔽——很多 DBA 只查 DBA_TAB_PRIVS,却忘了检查 DBA_ROLE_PRIVS 里是否悄悄塞了这个角色。











