只读用户必须显式授予SELECT权限,不可依赖角色继承;应逐表授权、用视图封装敏感字段、仅授CREATE SESSION系统权限,并注意表名大小写陷阱。
只读用户必须显式授予 SELECT 权限,不能依赖角色继承
oracle 默认不提供“只读用户”内置角色,select_catalog_role 看似方便,但实际会暴露大量数据字典表(如 dba_tables、dba_users),远超业务只读需求。生产环境误授这个角色等于变相开放元数据探测入口。
正确做法是绕过角色,对目标表逐个授权:
GRANT SELECT ON schema_name.table_name TO read_only_user;- 若涉及多个表,用脚本生成授权语句(避免手工漏表)
- 切勿对整个 schema 执行
GRANT SELECT ON schema_name.*—— Oracle 不支持该语法,会报错ORA-00905: missing keyword
视图封装敏感字段是更安全的只读方案
直接授表权限后,用户能查到所有列,包括身份证号、手机号等敏感字段。哪怕应用层做过滤,数据库层仍存在绕过风险。
推荐用视图隔离:
- 创建视图时仅
SELECT业务必需字段:CREATE VIEW v_emp_basic AS SELECT emp_id, name, dept FROM employees; - 只给用户授权视图:
GRANT SELECT ON v_emp_basic TO read_only_user; - 注意:视图依赖的基础表权限仍需由 DBA 持有,普通用户无需知道原表名
- 若视图含函数(如
SYS_CONTEXT)或连接多表,需确认执行计划是否引入额外开销
禁止授予 CREATE SESSION 以外的系统权限
新建用户后,很多人顺手加一堆权限:CREATE TABLE、CREATE VIEW、UNLIMITED TABLESPACE……这些和只读完全无关,且极易被滥用。
最小化系统权限清单只有这一条:
GRANT CREATE SESSION TO read_only_user;- 其他如
SELECT ANY TABLE、EXECUTE ANY PROCEDURE属于高危权限,绝对禁止 - 检查现有用户权限:运行
SELECT privilege FROM dba_sys_privs WHERE grantee = 'READ_ONLY_USER';,确保结果仅含CREATE SESSION
表名大小写与双引号陷阱
Oracle 默认把未加引号的标识符转为大写。如果建表时用了双引号定义小写或混合大小写表名(如 "userOrder"),后续授权必须严格匹配大小写和引号,否则报错 ORA-00942: table or view does not exist。
实操建议:
- 统一使用大写无引号命名,避免歧义
- 若已存在带引号的表,授权时必须写成:
GRANT SELECT ON schema."userOrder" TO read_only_user; - 用
SELECT table_name FROM all_tables WHERE owner = 'SCHEMA';查看真实存储名,别信开发给的“看起来一样”的名字
SELECT 授权必须精确到具体 schema.表,不能靠 synonym 或 public 同义词模糊处理。










