Базы данных Oracle - статьи

         

Контексты


Идея, лежащая в основе использования контекстов, очень проста и обеспечивает серьезную защиту. В исходном виде ее можно определить тремя особенностями: (i) контекст- список переменных в памяти, значения которых привязаны к сеансам, (ii) сеанс может получить текущие значения этих переменных, вызывая функцию sys_context(), (iii) переменные в контексте могут устанавливаться только путем вызова процедуры, связанной с этим контекстом. Например, используя служебную таблицу защиты, можно переписать предыдущий код следующим образом:

create or replace context security_ctx using security_proc; -- Процедура, защищающая контекст. -- Это может быть процедура пакета.

create or replace procedure security_proc as m_group_id varchar2(32); begin -- должна включать обработку исключительных ситуаций select group_id into m_group_id from security_table -- эту таблицу надо создать. where user_name = user; dbms_session.set_context( namespace => 'SECURITY_CTX', attribute => 'GROUP_ID', value => m_group_id ); end; /

create or replace trigger pt_bri before insert on public_table for each row begin :new.owner := sys_context('security_ctx','group_id'); -- должна включать перехват ошибок, например, null-значений end; /

create or replace view private_view as select id, v1 from public_table where owner = sys_context('security_ctx','group_id');

grant insert, select, update, delete on private_view to public;

При наличии этого кода, представление private_view ведет себя практически так же, как раньше. Пользователи, вставляющие данные в представление, автоматически получают при этом присоединенный к строке код группы. Пользователи, запрашивающие представление, увидят только строки, соответствующие коду их грруппы. Но, в этой реализации пока есть пробел. Как код группы пользователей устанавливается в их локальном контексте?

Для завершения картины надо использовать триггеры на регистрацию. Например, в схеме, в которой создана таблица, процедура и представление, можно выполнить следующий код:


create or replace trigger security_trigger after logon on database begin security_proc; end; /

Поскольку триггер срабатывает с привилегиями схемы, в которой он создан, он будет выполнять процедуру корректно, независимо от того, кто регистрируется в Oracle и вызывает его срабатывание. Это означает, что процедура, которая устанавливает контекст, не должна быть доступна ни одному другому пользователю, и поэтому ее нельзя использовать неправильно.

Хотя это достаточно мощный механизм для обеспечения защиты на уровне строк или поддержки виртуальной приватной базы данных, помните, что он зависит от срабатывания строчного триггера при каждой вставке в таблицу. Строчные триггеры требуют существенных дополнительных расходов на обработку и, в частности, они блокируют некоторые из высокоэффективных механизмов Oracle и преобразуют обработку массивов в построчную обработку.

Поэтому вы не должны использовать этот механизм, не учитывая и не проверив влияние на производительность - в частности, на процессы пакетной загрузки. Помните также, что вы можете найти примеры SQL-операторов, для которых оптимизатор вырабатывает менее эффективный способ выполнения, поскольку в коде приложения теперь надо использовать представление (private_view), а не таблицу (public_table), как раньше.

Будьте очень внимательны при написании триггеров на регистрацию, всегда тестируйте их на одной схеме (конструкция after logon on test_user.schema создаст триггер на регистрацию в схеме test_user), пррежде чем создавать их на уровне базы данных, или придется подключаться как SYS>, чтобы решить проблему, если что-то пойдет не так.

Для создания и удаления контекстов вам потребуются привилегии:

create any context drop any context

А для создания и удаления триггеров базы данных необходима привилегия

administer database trigger

Если вы хотите иметь возможность просматривать текущие значения переменных в используемых сейчас контекстах, можете предоставить пользователям привилегию для просмотра соответствующего представления динамической производительности, чтобы они могли выполнять запросы вида:

select namespace, attribute, value from sys.v_$context order by namespace, attribute;

NAMESPACE ATTRIBUTE VALUE -------------------- ----------------- ----------- SECURITY_CTX GROUP_ID T


Содержание раздела