Сбой политики VPD с ORA-28113: в предикате политики есть ошибка - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть таблица с именем payroll, созданная '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 

У меня также есть таблица с именами сотрудников, созданная также с помощью 'MANAGER', которая содержит:

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

У меня также есть, кроме 'MANAGER', два пользователя 'ALI' и 'SAMI', и я хочу ограничить их доступ к таблице 'payroll' в зависимости от их отделов, поэтому я дал им право выбора для обеих таблиц 'EMPLOYEES' и'payroll', и я написал следующую функцию политики:

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 голосов
/ 20 ноября 2018

Есть несколько вещей, которые приходят с FGAC, которые могут вызвать эту ситуацию.

Во-первых, если функция генерации предиката сама по себе недействительна, политика всегда выдает это исключение. В приведенном здесь примере присваивание v_user (строка 8) имеет двойные точки с запятой ;;, что должно привести к сбою компиляции.

Когда вы запускаете оператор create для sec_fun, вы должны получить следующее сообщение:

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;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...