oracle中不存在直接返回用户所有系统权限并集的视图,必须分层查询:用session_privs查当前会话生效权限,dba_sys_privs查直授权限,再通过dba_role_privs和role_sys_privs递归查角色权限。
查不到“总和”不是因为sql写得不够长,而是因为oracle里根本不存在一个视图能直接返回「用户所有系统权限的并集」——权限来源有三类:直授、角色继承、隐式授予(如create session),而它们生效与否还取决于会话状态。必须分层查、分层验,不能靠单条sql堆。
查当前用户实际生效的系统权限用 SESSION_PRIVS
这是最贴近运行时真实权限的视图,不需要DBA权限,结果即所见:
-
SESSION_PRIVS只返回当前会话已激活的系统权限,比如你刚执行了SET ROLE ALL,它立刻更新;但如果你被授予了RESOURCE角色却没启用,它就不会出现 - 它不区分来源——不管权限是直授的、还是从
CONNECT或RESOURCE角色来的,只要生效就列出来 - 它不包含对象权限,也不含
ADMIN_OPTION信息,结构干净,适合快速确认“我现在到底能干啥” - 执行
SELECT * FROM SESSION_PRIVS;即可,无条件、无连接、无权限门槛
查指定用户被直接授予的系统权限用 DBA_SYS_PRIVS
这个视图只记录显式GRANT ... TO user动作,不展开角色,也不管是否启用:
- 必须有
SELECT_CATALOG_ROLE或DBA权限才能访问,普通用户执行会报ORA-00942: table or view does not exist - 字段
GRANTEE存的是大写用户名,查'SCOTT'可以,查'scott'查不到;如果用户建时用了双引号(如"scott"),那必须严格匹配大小写+引号 -
ADMIN_OPTION = 'YES'表示该用户可再用WITH ADMIN OPTION转授此权限,但不意味着它当前在会话中生效 - 常见误判:看到
CREATE TABLE在DBA_SYS_PRIVS里,就以为用户能建表——但如果该权限来自角色且角色未启用,SESSION_PRIVS里照样没有
补全角色带来的系统权限得连查 DBA_ROLE_PRIVS + ROLE_SYS_PRIVS
角色是权限的主要载体,DBA_SYS_PRIVS里查不到的权限,大概率藏在角色里:
- 先查用户有哪些角色:
SELECT GRANTED_ROLE, DEFAULT_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE = 'SCOTT'; - 再对每个
GRANTED_ROLE去查它含哪些系统权限:SELECT PRIVILEGE FROM ROLE_SYS_PRIVS WHERE ROLE = 'RESOURCE'; - 注意:
ROLE_SYS_PRIVS本身对普通用户不可见,需DBA权限;而且它只展一层——如果APP_ADMIN角色又授予了SELECT_CATALOG_ROLE,那后者的权限不会自动出现在前者的查询结果里 - 生产环境审计时,必须递归展开角色链,否则权限评估严重偏低;简单场景下,手动查两到三层通常够用
为什么刚授的权限查不到?重点看会话生命周期
权限变更不是热更新,它依赖会话上下文重载:
- 用户已登录,你随后执行
GRANT CREATE TABLE TO scott;,该用户旧会话的SESSION_PRIVS不会变——必须重新连接,或执行SET ROLE ALL(如果涉及角色) -
DEFAULT_ROLE = 'YES'的角色,在登录时自动启用;但如果用户显式执行过SET ROLE NONE,那即使DEFAULT_ROLE为YES,该角色也不会激活 -
ALTER SESSION SET CURRENT_SCHEMA不影响SESSION_PRIVS输出,别指望靠它“切换权限上下文” - 最稳妥的验证方式:新开一个SQL*Plus或SQL Developer连接,再查
SESSION_PRIVS
真正难的不是拼SQL,而是厘清权限路径:某条SELECT ANY DICTIONARY到底是直授的、从DBA角色来的、还是嵌套在SELECT_CATALOG_ROLE里的?一旦漏掉一层角色,权限清单就不完整。不要迷信“总和”,要习惯分层验证。











