3. 用户与Schema安全设计
在Oracle数据库安全治理中,用户与Schema的设计是最基础、也最容易被忽视的一环。很多生产库之所以出现权限泛滥、对象归属混乱、表空间失控等问题,根源往往不在后期授权,而在最初建库建用户时就没有把“谁是谁、谁拥有什么、谁只能看什么”想清楚。本节围绕应用用户、个人用户、管理用户三类角色的划分,Schema隔离机制,表空间配额控制,以及默认权限策略四个维度,给出一套可落地的设计方法。
一、三类用户的职责边界
Oracle中的“用户”与“Schema”是两个容易混淆的概念:用户是登录数据库的账户,Schema是该用户名下对象的集合。一个用户默认拥有同名Schema,但通过ALTER SESSION SET CURRENT_SCHEMA可以切换当前操作的Schema。理解这一点,是做好隔离设计的前提。
从安全治理角度,建议把数据库账户划分为三类:
- 应用用户:供应用程序连接池使用,如
app_order、app_pay。这类账户只应拥有业务对象的最小DML权限,不应具备DDL权限,更不应有DBA角色。它们通常不直接拥有对象,而是通过被授权访问其他Schema的对象。 - 个人用户:供开发、运维、分析人员登录使用,如
zhangsan、lisi_dev。这类账户应绑定到具体人员,具备可审计性,权限按岗位授予,禁止多人共用。 - 管理用户:如
dba_admin、sec_admin,用于执行DDL、权限变更、备份恢复等管理操作。这类账户必须严格控制数量,启用强认证,并纳入操作审计。
三类账户的权限应呈现“倒金字塔”结构:应用用户权限最窄但数量最多,个人用户居中,管理用户权限最大但数量最少。任何跨类授权都需要经过审批。
二、Schema隔离的落地方式
Schema隔离的核心目标是:业务对象归属清晰,应用之间互不干扰,敏感数据可单独管控。推荐做法是按业务域划分Schema,例如订单域ord、支付域pay、用户域usr,每个Schema由独立的Schema Owner账户持有,应用用户通过同义词或直接授权访问。
隔离手段主要有三种:一是对象授权隔离,通过GRANT SELECT ON ord.orders TO app_order精确控制;二是同义词隔离,在应用用户下创建CREATE SYNONYM orders FOR ord.orders,屏蔽物理Schema名;三是Schema切换隔离,应用连接后执行ALTER SESSION SET CURRENT_SCHEMA=ord,使SQL中无需带Schema前缀。三种方式可组合使用,但要注意同义词会隐藏真实对象来源,审计时需结合DBA_SYNONYMS还原。
三、表空间配额控制
表空间配额决定了某个用户在特定表空间上能占用多少空间。默认情况下,新建用户在所有表空间上的配额为0,只有显式授予UNLIMITED TABLESPACE或具体配额后才能创建对象。生产环境应避免使用UNLIMITED TABLESPACE,改为按业务预估设置具体配额。
例如为订单Schema Owner设置配额:
CREATE USER ord IDENTIFIED BY "Ord#2024_Str0ng"
DEFAULT TABLESPACE tbs_ord
TEMPORARY TABLESPACE temp
QUOTA 2G ON tbs_ord
QUOTA 0 ON users;
GRANT CREATE SESSION, CREATE TABLE, CREATE INDEX,
CREATE SEQUENCE, CREATE PROCEDURE TO ord;
这里QUOTA 0 ON users是显式拒绝,防止用户误将对象建到系统表空间。当配额用尽时,插入或建表会报ORA-01536: space quota exceeded for tablespace,运维人员可通过DBA_TS_QUOTAS视图查看当前使用量:
SELECT username, tablespace_name, bytes, max_bytes
FROM dba_ts_quotas
WHERE username = 'ORD';
若MAX_BYTES = -1表示无限制,应重点排查这类账户。配额调整需走变更流程,调整后建议记录变更原因与预期增长量。
四、默认权限策略
Oracle用户创建后,默认没有任何权限,连登录都需要CREATE SESSION。但有两个容易踩坑的默认行为:一是PUBLIC角色默认拥有大量系统权限,如SELECT ON SYS.OBJ$等,新建用户会自动继承;二是ALTER DEFAULT ROLE若未设置,用户被授予的角色默认全部启用。
推荐策略是:
- 创建用户后立即执行
ALTER USER xxx DEFAULT ROLE NONE;,使角色默认不启用,需要时再SET ROLE。 - 收回不必要的
PUBLIC权限,尤其是SELECT ON DBA_*、EXECUTE ON UTL_*等敏感对象。 - 应用用户只授予对象级DML权限,不授予
SELECT ANY TABLE、UPDATE ANY TABLE等ANY权限。 - 个人用户按岗位建立角色,如
role_dev_read、role_dev_write,通过角色间接授权,便于批量回收。
DEFAULT TABLESPACE和TEMPORARY TABLESPACE,避免所有用户共用USERS表空间导致空间争用和审计困难。五、一份可参考的用户规划表
下表给出一个订单系统的用户规划示例,字段可根据实际项目调整:
| 用户名 | 类型 | 默认表空间 | 配额 | 默认角色 | 主要权限 |
|---|---|---|---|---|---|
| ord | Schema Owner | TBS_ORD | 2G | NONE | CREATE TABLE/INDEX/SEQUENCE |
| app_order | 应用用户 | USERS | 0 | NONE | SELECT/INSERT/UPDATE ON ord.* |
| zhangsan | 个人用户 | USERS | 0 | NONE | role_dev_read |
| dba_admin | 管理用户 | USERS | 0 | DBA | DBA 角色 + 审计 |
这张表的价值在于:它把“谁、在哪、能占多少、默认启用什么、能做什么”五个问题一次性说清楚。建库建用户时按表执行,后续权限复核时也按表核对,能显著降低权限漂移的风险。
CREATE ANY TABLE或DROP ANY TABLE权限。一旦应用被注入攻击,攻击者可能利用这些权限删除其他Schema的对象,造成跨业务破坏。用户与Schema安全设计不是一次性工作,而是需要随着业务演进持续维护的基线。建议每季度执行一次权限复核,重点检查:是否存在UNLIMITED TABLESPACE账户、是否存在未使用的个人账户、是否有应用用户被授予了ANY权限、PUBLIC角色是否被过度授权。把这些检查项固化成脚本,纳入日常巡检,才能真正把安全设计落到运行态。