oracle代理授权主体是被代理用户,正确语法为alter user zlhis grant connect through u1118;连接串必须为u1118[zlhis]/password;登录后需验证sys_context('userenv','authenticated_identity')返回u1118且user返回zlhis。

代理用户必须由被代理用户主动授权,不是“给代理用户赋权”
很多人卡在第一步:执行 ALTER USER U1118 GRANT CONNECT THROUGH ZLHIS 报错。这是方向反了——Oracle 的代理授权主体是「被代理用户」,不是代理用户。真正要运行的是:
-
ALTER USER ZLHIS GRANT CONNECT THROUGH U1118(ZLHIS 是应用 Schema 用户,U1118 是中间层服务账号) - 授权必须由
ZLHIS自己执行,或由 DBA 以AS SYSDBA代为执行;普通用户不能给自己授代理权限 - 执行后立即查
SELECT * FROM PROXY_USERS WHERE CLIENT = 'U1118' AND PROXY = 'ZLHIS',有记录才表示生效;没结果=没成功,别凭“语句没报错”就认为 OK
连接字符串里方括号位置和语法必须严格匹配
用 U1118 代理登录 ZLHIS,连接串格式是 U1118[ZLHIS]/password,不是 ZLHIS[U1118] 或 U1118@ZLHIS。常见错误现象:
- ORA-01017:用户名/密码无效 → 方括号写反、大小写不一致(Oracle 默认大写,除非双引号建用户)
- ORA-01045:user U1118 lacks CREATE SESSION privilege → 忘了给代理用户本身授
CREATE SESSION - 连得上但
SHOW USER显示 U1118 → 方括号缺失或格式错误,实际成了直连
验证方式:登录后立刻运行 SELECT SYS_CONTEXT('USERENV', 'AUTHENTICATED_IDENTITY') FROM DUAL,应返回 U1118;USER 函数返回 ZLHIS 才算代理成功。
JDBC 连接池里 setClientIdentifier 要每次请求前重设
CLIENT_IDENTIFIER 不是代理认证的替代品,但它能补上审计链最后一环:把真实终端用户(比如 Web 端的 user_id)注入会话上下文。问题在于连接池复用会导致值残留:
- 不调用
conn.unwrap(OracleConnection.class).setClientIdentifier("web_user_456")→ 审计日志里CLIENT_ID字段为空或沿用旧值 - 只在连接初始化时设一次 → 后续多个业务请求共用同一连接,
CLIENT_ID始终是第一个用户的标识 - 正确做法:在每次业务逻辑开始前(如 Spring AOP @Before、Servlet Filter、或 ORM 的 Connection Hook 中)显式设置
注意:setClientIdentifier 对权限无影响,只影响 DBA_AUDIT_TRAIL.CLIENT_ID 和 SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') 的取值。
被代理用户锁定了还能连,代理用户锁定了也能连,但两者都不可删
Oracle 代理机制的设计原则是「身份可分离、账户可隔离」:
- 即使
ZLHIS账户被ALTER USER ZLHIS ACCOUNT LOCK,只要U1118没锁,U1118[ZLHIS]仍可登录(权限继承自 ZLHIS 的角色和对象授权) - 即使
U1118被锁,只要它之前已获代理权限,且连接池中已有活跃会话,那些会话仍可继续工作(但新连接失败) - 切勿
DROP USER ZLHIS CASCADE—— 代理关系不会自动清理,PROXY_USERS视图可能残留脏数据,且依赖该 Schema 的应用直接崩
真正要清理时,先运行 ALTER USER ZLHIS REVOKE CONNECT THROUGH U1118,再确认 PROXY_USERS 无记录,最后才删用户。漏掉 revoke 步骤,下次重建同名用户时可能意外继承旧代理关系。











