VPD策略失败,并显示ORA-28113:策略谓词有错误

时间:2018-11-19 20:06:35

标签: oracle plsql

我有一个由“ MANAGER”创建的名为薪资表,其中包含以下内容:

EMP_ID               DEPT                      TOTAL      TAXES
-------------------- -------------------- ---------- ----------
E1                   accounting                 2400        100 
E2                   sales                      2500         75 
E3                   research                   3000        110 
E4                   operations                 4200        120 
E5                   sales                      4800        130 
E6                   sales                      2500         75 
E7                   accounting                 5200        140 
E8                   accounting                 2700        105 

我还有一个名为“ employees”的表,它也是由“ MANAGER”创建的,包含:

ENAME                USER_ID              DEPT               
-------------------- -------------------- --------------------
SAMI                 E4                   operations           
ALI                  E7                   accounting           
MIRIAM               E5                   sales    

在“ MANAGER”旁边还有两个用户“ ALI”和“ SAMI”,我想根据他们的部门来限制他们对“工资”表的访问,因此我给他们两个表“ EMPLOYEES”和“ “工资单”,我编写了以下政策功能:

create or replace function sec_fun (p_schema varchar2, p_obj varchar2)
return varchar2
as
    v_dept MANAGER.employees.dept%type;
    v_user varchar2(100);
    v_id MANAGER.employees.user_id%type;
begin
    v_user:= SYS_CONTEXT('userenv', 'SESSION_USER');;
    select dept,user_id into v_dept, v_id from MANAGER.EMPLOYEES where ename=v_user;
    if (v_dept!= 'accounting') then
        return 'EMP_ID=' ||v_id;
    else
        return 'DEPT !=' || v_dept;
    end if;
exception
    when NO_DATA_FOUND then
        return null;
end;
/

然后我写了:

begin
    dbms_rls.add_policy(
      'MANAGER',
      'payroll',
      'p1',
      'MANAGER',
      'sec_fun',
      'select');
end;
/

现在,当我以“ ALI”身份连接时,写

SELECT * FROM MANAGER.PAYROLL;

在通过互联网阅读各种解决方案后,我多次查看并编辑了策略功能,并遇到以下错误:

Error at Command Line:1 Column:23
Error report:
SQL Error: ORA-28113: policy predicate has error
*Cause:    Policy function generates invalid predicate.
*Action:   Review the trace file for detailed error information.

非常感谢您的帮助。预先谢谢你

1 个答案:

答案 0 :(得分:0)

FGAC附带有一些事情可以触发这种情况。

首先,如果谓词生成函数本身无效,则策略将始终抛出此异常。在此处提供的示例中,v_user(第8行)的分配具有双分号;;,这将导致编译失败。

运行sec_fun的create语句时,应该收到如下消息:

Warning: Function created with compilation errors.
Elapsed: 00:00:00.483

由于谓词生成器存在语法错误,因此应用于PAYROLL的策略将总是失败,并带有ORA-28113

要注意的一件事是ORA-28113包含一个有用的建议:
 “ Review the trace file for detailed error information.
当策略失败时,数据库将写入详细描述根本原因的跟踪文件。

无论如何,在删除双分号之后,至少应该编译一下。但是,迫在眉睫的其他问题也将触发这种情况。

接下来的问题是,所编写的return语句不是有效谓词,因为它们没有创建有效的string literals

例如,“ EMP_ID = E1”不可用,因为它包含了没有用引号引起来的文字。 “ DEPT != accounting”谓词也是如此。

在下面的重做版本中,已引用了这些内容。

此外,FGAC通常希望从所有执行分支中提供有效的谓词。
NULL在您的情况下可行时,也许返回NO_DATA_FOUND,但最好返回一个有效的谓词(过滤所有数据)。您可能更愿意为不存在的雇员抛出异常。在这种情况下,NULL是可以接受的。这只是一个建议/想法。

要注意的另一件事是,使用SYS_CONTEXT可能会带来一些麻烦,并且比要求的更为冗长。除非进行某种间接/嵌套/代理操作会导致当前用户不正确,否则可以只使用USER函数,并避免一些sys_context复杂性。

这里是替代版本,应该编译,而不是抛出错误,并按照您描述的内容进行过滤:

CREATE OR REPLACE FUNCTION SEC_FUN(P_SCHEMA VARCHAR2 , P_OBJ VARCHAR2) RETURN VARCHAR2 
AS
  V_DEPT EMPLOYEES.DEPT%TYPE;
  V_ID EMPLOYEES.USER_ID%TYPE;
BEGIN
  SELECT EMPLOYEES.DEPT, EMPLOYEES.USER_ID INTO V_DEPT, V_ID FROM MANAGER.EMPLOYEES WHERE EMPLOYEES.ENAME = USER;
  IF (V_DEPT != 'accounting')
  THEN
    RETURN 'EMP_ID = ' || CHR(39)||V_ID||CHR(39);
  ELSE
    RETURN 'DEPT != ' || CHR(39)||V_DEPT||CHR(39);
  END IF;
  EXCEPTION
  WHEN NO_DATA_FOUND
  THEN
    RETURN '1 = 0';
END;
/