Oracle 的权限分两类:
系统权限管「能做什么动作」(建表、建会话),对象权限管「能碰哪个对象」(查这张表)。
带 ANY 的系统权限是跨模式的——一句 SELECT ANY TABLE 等于「能看全库」。
这类权限是审计重点,生产上不该给业务账号。
12.2 讲「建账号」。这一篇讲「授权」。 建完账号不授权,这个账号连登录都不行——这一点很多人第一次遇到会愣住。 这一篇还讲「撤销」,因为撤销比授权更容易出错: 直接授的和角色授的是两条路,撤了一条另一条还通着。
一、系统权限:动作级别
系统权限管的是「你能执行什么语句」。
一共一百多个,常用的七八个:
CREATE SESSION(能连)、CREATE TABLE(能建表)、CREATE VIEW、CREATE SEQUENCE、
CREATE PROCEDURE。
带 ANY 的是另一类:
SELECT ANY TABLE、DROP ANY TABLE、CREATE ANY TABLE。
它们的作用范围是「全库所有模式」,
所以一句 GRANT SELECT ANY TABLE 就等于「能看所有人的数据」。
这一类权限的本质是「绕过模式隔离」。
正常情况下,你只能碰自己模式的对象;ANY 权限把这个限制去掉了。
所以审计的时候,第一个查的就是「谁有 ANY 权限」。
二、对象权限:对象级别
对象权限只有七种:
SELECT、INSERT、UPDATE、DELETE、ALTER、INDEX、REFERENCES。
REFERENCES 这个最不直观:它管的是「能不能在这个表上建外键」。
你要在 emp 上建一个指向 dept 的外键,就得有 dept 的 REFERENCES 权限——
因为外键会让你的表「依赖」别人的表,得人家同意。
INDEX 权限也容易被忽略:
在自己的表上建索引不需要它,在【别人的表】上建索引才需要。
这个权限存在的原因很实际:建索引会影响别人表的写入性能。
三、授权语法:三个位置别搞错
系统权限:GRANT CREATE TABLE TO scott;
没有 ON,因为它是「动作权限」,不针对具体对象。
对象权限:GRANT SELECT ON hr.emp TO scott;
必须有 ON 对象。
授角色:GRANT r_read TO scott;
形式上和系统权限一样(没有 ON),但授的是角色不是权限。
这三个位置混起来就会报错,而且报错信息不一定直观。
记住一句话:
「ON 后面跟对象」就是对象权限,没有 ON 就看 TO 前面是权限名还是角色名。
四、WITH GRANT OPTION 与级联撤销
GRANT SELECT ON hr.emp TO scott WITH GRANT OPTION;
多了这一句,scott 就能把这份权限再授给别人。
它的麻烦在「级联」:
hr 收回 scott 的权限时,scott 授出去的也一起被收回。
这叫级联撤销(cascade revoke)。
所以排查「谁能看这张表」时,不能只看直接授权。
要看 DBA_TAB_PRIVS(谁被授了什么),还要顺着 GRANTOR 那一列往上追——
因为同一个权限可能有好几条授权链。
生产上建议:WITH GRANT OPTION 只给「权限管理员」,不给普通业务账号。
不然授权链会长成一棵树,谁也说不清谁有什么。
五、撤销:直接授的和角色授的是两条路
REVOKE SELECT ON hr.emp FROM scott;
这一句撤的是「直接授给 scott 的那一份」。
如果 scott 同时通过角色拿到了同样的权限,撤完他还能查。
因为「直接授」和「角色授」是两条独立的路径,撤一条另一条还通着。
这就是权限排查难的根本原因:
「为什么他还能查」的答案往往不是「撤销失败」,而是「还有另一条路」。
排查顺序建议四步:
① 查 DBA_TAB_PRIVS 看直接授权。
② 查 DBA_ROLE_PRIVS 看他有哪些角色。
③ 查 ROLE_TAB_PRIVS 看角色里有没有这个权限。
④ 再看有没有 PUBLIC 的授权(PUBLIC 是「所有人」)。
六、动手 Demo:系统权限、对象权限、角色三层,各查一遍
沙箱里没有 GRANT,但权限判定就是个集合运算——
「直接授的」并上「角色里的」,再看要的那个在不在。
这个模型能真跑,而且能复现几个经典现象。
特别看第二节:一个刚建好的用户,连 CREATE SESSION 都没有,登录直接被拒。
这不是极端情况,是每一个新用户的默认状态。
# 权限判定:系统权限看动作,对象权限看对象,角色是中间层
SYS = {"scott": {"CREATE SESSION"}, "hr": {"CREATE SESSION", "CREATE TABLE"}}
OBJ = {("scott", "hr.emp"): {"SELECT"}}
ROLES = {"r_read": {"CREATE SESSION", "SELECT:hr.emp", "SELECT:hr.dept"}}
MEMBERS = {"scott": {"r_read"}, "hr": set()}
def sys_privs(u):
out = set(SYS.get(u, set()))
for r in MEMBERS.get(u, set()):
out |= set(x for x in ROLES.get(r, set()) if ":" not in x)
return out
def obj_privs(u, obj):
out = set(OBJ.get((u, obj), set()))
for r in MEMBERS.get(u, set()):
out |= set(x.split(":")[0] for x in ROLES.get(r, set())
if x.startswith("SELECT:") and x.split(":")[1] == obj)
return out
for who in ("scott", "hr"):
print(who, "系统权限:", sorted(sys_privs(who)) or "(空)",
"| 对 hr.emp 的对象权限:", sorted(obj_privs(who, "hr.emp")) or "(空)")
print("注意 scott 的 CREATE SESSION 不是直接授的,是从角色 r_read 里来的。")
实跑输出:
--------------------------------------------------------------------
第五十五课:用户权限——系统权限与对象权限
--------------------------------------------------------------------
**Oracle 的权限分两类,分界线很清楚:** **系统权限管「能做什么动作」(建表、建会话)。**
**对象权限管「能碰哪个对象」(查这张表、改那张表)。**
一、系统权限:动作级别
--------------------------------------------------------------------
**一共一百多个,常用的就七八个:**
系统权限 能干什么
--------------------------------------------------
CREATE SESSION 能连上数据库(最基本的)
CREATE TABLE 能在自己模式下建表
CREATE ANY TABLE 能在【任何】模式下建表(危险)
DROP ANY TABLE 能删任何模式的表(危险)
SELECT ANY TABLE 能查任何表(危险)
GRANT ANY PRIVILEGE 能给别人授权(极危险)
已选择 6 行
**注意 `ANY` 这个词。**
**带 `ANY` 的权限是「跨模式」的,一句 `GRANT SELECT ANY TABLE` 就等于「能看全库」。**
**这类权限是审计重点**—— **生产上给业务账号授 `ANY` 权限,基本等于放弃了权限管理。**
二、实测:没有 CREATE SESSION 连不上
--------------------------------------------------------------------
**`scott` 现在的系统权限集合:(空)**
**能不能连?不能**
SQL> connect scott/tiger
ERROR:
ORA-01045: 用户 SCOTT 没有 CREATE SESSION 权限;登录被拒绝
**这说明一件事:`CREATE USER` 建出来的账号是「什么都不能干」的。** **连登录都不行。**
**所以建用户的完整流程一定是「建用户 + 授 `CREATE SESSION` + 授业务权限」。**
三、对象权限:对象级别
--------------------------------------------------------------------
被授予者 对象 能做什么
------------------------
scott hr.emp SELECT
已选择 1 行
**`GRANT SELECT ON hr.emp TO scott;`** **这一句只让 `scott` 能【查】`hr.emp`**,
**不能改、不能删,也不能查 `hr` 的其他表。**
**对象权限一共就七种:**
**`SELECT`、`INSERT`、`UPDATE`、`DELETE`、`ALTER`、`INDEX`、`REFERENCES`。**
**比系统权限少得多,也细得多。**
四、WITH GRANT OPTION:把授权权也传下去
--------------------------------------------------------------------
被授予者 对象 权限
----------------------
scott hr.emp SELECT
smith hr.emp SELECT
已选择 2 行
**`GRANT SELECT ON hr.emp TO scott WITH GRANT OPTION;`**
**多了这一句,`scott` 就能把这个权限再授给别人。**
**它的麻烦在于「级联」:** **`hr` 收回 `scott` 的权限时,`scott` 授出去的也一起被收回。**
**这叫级联收回(cascade revoke)。**
**所以排查「谁能看这张表」时,不能只看直接授权,得顺着授权链一路查。**
五、撤销:REVOKE 的两个层次
--------------------------------------------------------------------
**撤系统权限:`REVOKE CREATE TABLE FROM scott;`**
**撤对象权限:`REVOKE SELECT ON hr.emp FROM scott;`** **两句结构一样,但作用范围差很远。**
**撤完之后 `scott` 还能看 `hr.emp` 吗?不能**
**如果 `scott` 是通过角色拿到的这个权限,`REVOKE` 直接授的那份是撤不掉的**——
**因为「直接授」和「角色授」是两条独立的路径。**
**这就是权限排查难的地方:一条路堵了,另一条还通着。**
第一段:一堆系统权限的对照表。
注意带 ANY 的那几个,作用范围是「全库」——它们绕过了模式隔离,所以是审计的重点。
第二段:scott 刚建好,权限集合是空的,连不上。
报 ORA-01045。
所以「建用户」的完整流程一定是三步:建用户、授 CREATE SESSION、授业务权限。
第三段:授了 SELECT ON hr.emp 之后,scott 能查这一张表。
注意「只能查这一张」——hr 的其他表他还是看不见。对象权限是「一个对象一份授权」。
第四段:WITH GRANT OPTION 让授权链能传下去。
我的模型里只记录「谁有什么」,没模拟「谁授给谁的」——
真实 Oracle 里那一列叫 GRANTOR,级联撤销就是顺着它找下游。
第五段:撤销之后不能查了。
但如果他还有角色,角色里也有这个权限,撤完照样能查——最后一句说的就是这个坑。
30 秒实验
- 把
MEMBERS["scott"]改成{"r_read"}保留,同时删掉OBJ[("scott", "hr.emp")], 看scott还能不能查hr.emp——能,因为角色里还有。 - 给
hr加一个SELECT ANY TABLE系统权限,想想这算不算「对象权限」。 不算——它是系统权限,效果是「不用逐表授权就能查」,本质是绕过模式隔离。 - 把
ROLES改成两层(r_read授给r_write),看sys_privs要不要递归——要, 这就是「角色嵌套」的代价。
常见误区
- 「建了用户就能连」。 不能。还要
CREATE SESSION。 每一个新用户的默认状态都是「什么都不能干」。 - 「授了
SELECT ON hr.emp就能看hr的所有表」。 不能。对象权限是一个对象一份授权。 - 「
REVOKE之后他就查不了了」。 如果有角色或PUBLIC授权,照样能查。 撤销失败最常见的原因是「还有另一条路」。 - 「
WITH GRANT OPTION只是方便」。 它会长出授权树,级联撤销时一片一片地掉, 排查难度指数上升。
自测三问(点开对答案)
1. 系统权限和对象权限的分界线是什么? —— **系统权限管「动作」(能不能建表),对象权限管「对象」(能不能查这张表)。** **语法上:有 `ON` 的是对象权限。** 2. `SELECT ANY TABLE` 属于哪一类? —— **系统权限。** 它的效果是「跨模式查」,本质是绕过模式隔离。**审计重点。** 3. 为什么撤销了权限,用户还能查? —— **因为还有另一条路:角色、`PUBLIC` 授权、或者别的授权链。** **「直接授」和「角色授」是两条独立的路径。** 4. `REFERENCES` 权限是干什么的? —— **让你能在自己的表上建指向别人表的外键。** **因为外键会让你的表依赖别人的表,得人家同意。**下一篇讲角色:把一组权限打包起个名字。 它的价值不在技术,在运维——20 个人同一个权限组合,授 1 次不是 20 次。
- ☐ (本篇完,下一篇 12.4 角色管理)
相关笔记
- 创建与管理用户
- 角色管理
- 用户与模式的关系
-
- 🐬 MySQL必知必会/00-索引
- 🏺 Oracle从入门到精通 · 索引