我有一个由“ 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.
非常感谢您的帮助。预先谢谢你
答案 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;
/