Oracle 19c VPD函数中SYS_CONTEXT('SYS_SESSION_ROLES','DBA')返回异常
问题原因与解决方案
核心原因
Oracle中,默认创建的PL/SQL函数采用定义者权限(AUTHID DEFINER)执行,此时会话中的角色会被禁用——只有直接授予用户的系统权限会生效,通过角色赋予的权限(比如DBA角色)在函数内部无法被识别。这就是直接执行SQL时SYS_CONTEXT('SYS_SESSION_ROLES', 'DBA')返回TRUE,但在VPD策略函数中返回FALSE的根本原因。
而SYS_CONTEXT('USERENV', 'SESSION_USER')不受角色权限机制影响,因此在两种场景下结果一致。
解决方案
方案1:修改函数为调用者权限执行
修改函数定义,添加AUTHID CURRENT_USER子句,让函数在当前用户的会话上下文(包含已启用的角色)中执行:
CREATE OR REPLACE FUNCTION show_own_salary(v_schema IN VARCHAR2, v_obj IN VARCHAR2) RETURN VARCHAR2 AUTHID CURRENT_USER -- 添加调用者权限声明 AS condition VARCHAR2 (200); BEGIN IF SYS_CONTEXT('SYS_SESSION_ROLES', 'DBA') = 'TRUE' THEN RETURN ''; END IF; IF SYS_CONTEXT( 'SYS_SESSION_ROLES', 'ALL_ACCOUNTANT' ) = 'TRUE' THEN RETURN ''; END IF; RETURN 'SID = (SYS_CONTEXT(''USERENV'', ''SESSION_USER'' ))'; END show_own_salary;
方案2:直接授予用户所需权限(不推荐)
如果不想修改函数权限属性,可以直接将DBA权限(或VPD策略依赖的其他权限)直接授予用户,而非通过角色赋予。但这种方式缺乏灵活性,不利于统一权限管理。
验证步骤
修改函数后,重新绑定VPD策略并测试:
-- 先删除原有VPD策略(假设策略绑定在EMP表) BEGIN DBMS_RLS.DROP_POLICY( object_schema => '你的模式名', object_name => 'EMP', policy_name => '你的VPD策略名' ); END; / -- 重新添加VPD策略 BEGIN DBMS_RLS.ADD_POLICY( object_schema => '你的模式名', object_name => 'EMP', policy_name => '你的VPD策略名', function_schema => '函数所在模式', policy_function => 'show_own_salary', statement_types => 'SELECT' ); END; / -- 测试查询 SELECT * FROM EMP;
内容的提问来源于stack exchange,提问作者user20137254
相关产品推荐
相关产品推荐

