В этой статье я хотел бы рассказать о решении, позволяющем организовать ограничения доступа к данным на уровне СУБД, и в том случае, когда в самой ограниченной таблице содержатся данные, влияющие на ограничение.
Пример, который я приведу, сильно упрощен, но необходимые инструменты, используемые в решении, представлены комплексно.
Протестировано на Oracle 11g R2. Предположим, пользователю SCOTT понадобилось ограничить доступ к данным некоторых таблиц, но критерии, по которым должен быть предоставлен доступ, выглядят так, будто он требует анализа данных ограниченной таблицы.
Казалось бы, что может быть проще – поехали.
Давайте установим соединение с базой данных от имени СКОТТ и создадим таблицы, одна из которых будет содержать список пользователей с доступом, а вторая сами данные:
Все прошло гладко.CREATE TABLE scott.user_allowed ( ua_id NUMBER, oracle_user VARCHAR2(50) ); Table created. insert into scott.user_allowed (ua_id, oracle_user) values (1, 'SCOTT'); insert into scott.user_allowed (ua_id, oracle_user) values (2, 'OTHERUSER'); 1 row created. 1 row created. commit; CREATE TABLE scott.user_data ( ud_id NUMBER, ud_user_id NUMBER, ud_data VARCHAR2(2000) ); Table created. insert into scott.user_data (ud_id, ud_user_id, ud_data) values (1, 1, 'SCOTT DATA'); insert into scott.user_data (ud_id, ud_user_id, ud_data) values (2, 2, 'OTHERUSER DATA'); 1 row created. 1 row created. commit; select ud_id, ud_user_id, ud_data from user_data; 2 rows selected.
Теперь давайте подключимся от имени СИС , давайте создадим функцию-предикат и политику безопасности: CREATE OR REPLACE FUNCTION sys.scott_predicate_allow
(
obj_schema IN VARCHAR2, obj_name IN VARCHAR2
)
RETURN VARCHAR2
IS
BEGIN
return 'ud_id in (SELECT ud_id FROM scott.user_data ud, scott.user_allowed ua WHERE ud.ud_user_id = ua.ua_id AND upper(ua.oracle_user) = upper(USER))';
END scott_predicate_allow;
/
Function created.
BEGIN
SYS.DBMS_RLS.ADD_POLICY
(
Object_schema => 'SCOTT'
,Object_name => 'USER_DATA'
,policy_name => 'SCOTT_ALLOW_USER_DATA'
,function_schema => 'SYS'
,policy_function => 'SCOTT_PREDICATE_ALLOW'
,statement_types => 'SELECT,INSERT,UPDATE,DELETE,INDEX '
,policy_type => dbms_rls.dynamic
,long_predicate => FALSE
,sec_relevant_cols => 'UD_ID,UD_USER_ID,UD_DATA'
,sec_relevant_cols_opt => NULL
,update_check => FALSE
,enable => TRUE
);
END;
/
PL/SQL procedure successfully completed.
Всё, теперь пользователь СКОТТ при доступе к таблице ДАННЫЕ ПОЛЬЗОВАТЕЛЯ , увидит только те данные, которые находятся в столбце ud_user_id принадлежат ему, согласно настройке в таблице ПОЛЬЗОВАТЕЛЬ_РАЗРЕШЕН .
Остается только это проверить, авторизуемся еще раз как СКОТТ И: select ud_id, ud_user_id, ud_data from user_data;
ORA-28113: policy predicate has error
Для того, чтобы определить, в чем заключается ошибка, вам необходимо просмотреть файл трассировки, который содержит подробное описание: ORA-28108: circular security policies detected
Фактически, я бы назвал это аналогом мутации триггера.
Для решения возникшей проблемы можно использовать… как показала практика, не так уж и много.
Если хотите, попробуйте сами, но учитывая, что реальная задача будет сильно отличаться от приведенного примера.
Вернемся к подключению от имени СИС и выполните: create or replace type sys.number_table is table of number;
/
Type created.
CREATE OR REPLACE PACKAGE SYS.SCOTT_ALLOWED AS
allowed_id number_table:=number_table();
function get_allowed_id return number_table;
END SCOTT_ALLOWED;
/
Package created.
CREATE OR REPLACE PACKAGE BODY SYS.SCOTT_ALLOWED AS
function get_allowed_id return number_table is
begin
return allowed_id;
end;
END SCOTT_ALLOWED;
/
Package body created.
CREATE OR REPLACE FUNCTION sys.scott_predicate_allow
(
obj_schema IN VARCHAR2, obj_name IN VARCHAR2
)
RETURN VARCHAR2
IS
BEGIN
scott_allowed.allowed_id:=number_table();
select ud_id bulk collect into scott_allowed.allowed_id
from scott.user_data ud,
scott.user_allowed ua
where ud.ud_user_id = ua.ua_id
and upper(ua.oracle_user) = upper(USER);
return 'EXISTS (SELECT 1 FROM TABLE(scott_allowed.get_allowed_id) a WHERE a.column_value = ud_id)';
END scott_predicate_allow;
/
Function created.
Первое, что было сделано, — это объявить новый тип данных, отражающий таблицу с одним типом столбца.
ЧИСЛО .
Этот тип будет использоваться для переменной пакета, в которую будет выбран список идентификаторов, к которым будет предоставлен доступ.
Функция в пакете представляет собой обертку, позволяющую осуществлять обратный доступ к данным.
С содержимым переменной пакета между сессиями проблем не возникнет, так как для каждой сессии выделяется отдельная область памяти.
Предполагая, что целью курсора в функции-предикате является определение идентификаторов первичного ключа таблицы, целесообразнее модифицировать сгенерированное ограничение в конструкцию СУЩЕСТВУЕТ .
Теперь проверим результат проделанной работы, подключившись от имени СКОТТ : select ud_id, ud_user_id, ud_data from user_data;
1 row selected.
Теги: #oracle #oracle 11.2 #oracle 11g #политики безопасности oracle #oracle
-
Хабрахабре Исполнилось 8 Лет.
19 Oct, 24 -
Семь Руководящих Принципов Itil 4
19 Oct, 24 -
Выбор Хостинга: Скорость И Надежность
19 Oct, 24 -
Zap-Ридер
19 Oct, 24 -
Google Search Api В Стиле Web 2.0
19 Oct, 24 -
Gamma Gallery — Отличная Адаптивная Галерея.
19 Oct, 24