Oracle创建角色必须显式指定IDENTIFIED BY或NOT IDENTIFIED;未认证角色无法后期添加密码,需重建;批量授权应通过DBA_OBJECTS生成GRANT语句而非SELECT ANY TABLE;WITH ADMIN OPTION存在权限扩散风险;角色嵌套超2层会触发ORA-01927;权限变更需重新连接或SET ROLE生效。
Oracle 中创建角色时,CREATE ROLE 默认创建的是“非认证角色”(即 NOT IDENTIFIED),这种角色不能被密码保护,也不能用于外部身份验证。如果你后续想用 SET ROLE role_name IDENTIFIED BY ... 切换角色,就必须在建角色时加上 IDENTIFIED BY 子句。
常见错误是漏写该子句,导致后续无法以密码方式激活角色:
CREATE ROLE app_reader; -- ✅ 非认证角色,可直接 GRANT/REVOKE
CREATE ROLE app_reader IDENTIFIED BY "R3ad@2026"; -- ✅ 支持密码切换
若已建好未认证角色,无法后期 ALTER 添加密码 —— 只能 DROP ROLE 后重建。
给角色批量授予某 schema 下所有表的 SELECT 权限,最安全的做法不是授 SELECT ANY TABLE(高危,绕过所有权控制),而是查 DBA_OBJECTS 生成语句。
在 SYS 或具有 SELECT_CATALOG_ROLE 的用户下执行:
SELECT 'GRANT SELECT ON ' || owner || '.' || object_name || ' TO app_reader;' FROM dba_objects WHERE owner = 'HR' AND object_type = 'TABLE';
GRANT SELECT ON hr.employees TO app_reader; 类语句,复制执行即可owner 必须大写(如 'HR'),否则可能漏匹配OR object_type IN ('VIEW', 'SEQUENCE')
给角色授系统权限(如 CREATE SESSION、CREATE TABLE)时,加 WITH ADMIN OPTION 意味着该角色持有者可以再把这权限转授给别人——这会脱离 DBA 控制面。
典型误用场景:
GRANT CREATE TABLE TO app_dev WITH ADMIN OPTION; → app_dev 用户可自行 GRANT CREATE TABLE TO attacker_user;
WITH ADMIN OPTION
查谁有转授权:运行 SELECT * FROM dba_sys_privs WHERE admin_option = 'YES';
Oracle 允许角色 A 授予角色 B,B 再授予角色 C,但嵌套层级默认上限为 2(即 A→B→C 是合法的,A→B→C→D 就不行)。超限时报错:ORA-01927: cannot revoke privileges you did not grant 或登录后权限不生效。
排查方法:
SELECT * FROM session_roles;
SELECT granted_role FROM dba_role_privs WHERE grantee = 'APP_READER';
真正容易被忽略的是:角色继承关系在用户会话建立时固化,改完角色权限后,已有连接不会自动刷新 —— 必须让用户重新 CONNECT 或执行 SET ROLE 才生效。