#oracle #plsql #row-level-security
#Oracle #plsql #безопасность на уровне строк
Вопрос:
У меня следующая проблема: я хочу внедрить «Политику безопасности на уровне строк» в таблицу в моей базе данных и добавил эту функцию:
FUNCTION app_user_is_master_owner(
schema_in IN VARCHAR2,
object_in IN VARCHAR
)
RETURN VARCHAR2
IS return_value VARCHAR2(100);
BEGIN
SELECT 'OWNER_FK = ' ||
(SELECT mo.owner_id
FROM MASTER_OWNER mo
WHERE upper(mo.owner_name) = SYS_CONTEXT('USERENV', 'SESSION_USER')) ||
' OR OWNER_FK IS EMPTY'
INTO return_value
FROM DUAL;
RETURN return_value;
END app_user_is_master_owner;
Я вызвал ADD_POLICY из DBMS_RL, чтобы добавить его в другие политики
BEGIN
DBMS_RLS.ADD_POLICY(
object_schema => 'MY_SCHEMA',
object_name => 'MASTER_DATA',
policy_name => 'app_user_is_mo_policy',
function_schema => 'MY_SCHEMA',
policy_function => 'MY_RLS_POLICYS.app_user_is_master_owner',
statement_types => 'SELECT, INSERT, UPDATE, DELETE'
);
END;
Когда я вызываю функцию в sql plus, не добавляя ее в качестве политики RLS, возвращается ожидаемое предложение ‘where’
SQL> select my_rls_policys.app_user_is_master_owner('A','A') from dual;
MY_RLS_POLICYS.APP_USER_IS_MASTER_OWNER('A','A')
--------------------------------------------------------------------------------
OWNER_FK = 4000 OR OWNER_FK IS EMPTY
но если я назову это как VPD-Policy, появится это сообщение об ошибке.
SQL> SELECT * FROM MASTER_DATA;
SELECT * FROM MASTER_DATA
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected UDT got NUMBER
Я думаю, это потому, что результатом является Select, а не VARCHAR , но добавление TO_CHAR ни к «select to_char(…) в return_value», ни к «return TO_CHAR(return_value)», похоже, не решает проблему.
Другие политики работают просто отлично.
Спасибо за вашу помощь.
Matthias
Ответ №1:
Попробуйте получить владельца переменной, а затем объединить
function app_user_is_master_owner(
schema_in in varchar2,
object_in in varchar
) return varchar2
is
predicate varchar2(100);
owner_id master_owner.owner_id%type;
begin
select owner_id
into owner_id
from master_owner
where upper(owner_name) = sys_context('userenv', 'session_user');
predicate := '(owner_fk = ' || owner_id || ' or owner_fk is null)';
return predicate;
end app_user_is_master_owner;
P.S не уверен, что is empty
это значит… я изменил его на is null
.
Комментарии:
1. Еще две вещи, пока вы на это, определите больший размер для сгенерированной строки, такой как предикат (я обычно использую ограничение для synamic string ~ varchar2(4001)) и добавьте случай для
NO_DATA_FOUND
.2. Я рассмотрю это, прямо сейчас это просто пример для руководства, которое я пытаюсь сделать. Но спасибо за совет.