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

         

История


С момента появления триггеров в Oracle было легко реализовать простой вид контроля доступа к данным на основе имени пользователя, комбинируя таблицу, представление и триггер. Рассмотрим, например, представленный ниже код:

create table public_table ( id number(6), v1 varchar2(30), owner varchar2(32));

create or replace trigger pt_bri before insert on public_table for each row begin new.owner := user; end; /

create or replace view private_view as select id, v1 from public_table where owner = user;

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

Если теперь создать пару пользователей с привилегией create session, вы увидите, что они могут выбирать, вставлять, изменять и удалять строки из представления private_view (если они не забудут указать имя схемы, которой он принадлежит), но увидеть они смогут только строки, которые они создали сами. Они не смогут увидеть строки друг друга. Триггер гарантирует, что имя пользователя, создающего строку, добавляется к строке; условие "owner = user" гарантирует, что только исходный создатель строки сможет ее увидеть.

(Учтите - строка pl/sql-кода :new.owner := user приведет к выполнению "select user from dual", так что, в эффективной производственной системе, вероятно, придется использовать более "хитрый" код).

Только владелец таблицы сможет увидеть все строки; но это потому, что владелец таблицы может запрашивать непосрредственно таблицу, а не ограничиваться представлением. Фактически, у нас есть один, фиксированный текст представления, который интерпретируется по-разному во время выполнения, из-за "псевдо-параметра" user, который появляется в его определении.

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


Конечно, основанный на группах механизм вроде описанного тоже можно было реализовать давно, и обычно для реализации использовалась функция в пакете, которую можно было использовать как в представлении, так и в триггере практически так же, как выше использовался псевдостолбец user. Но этот метод требует значительных дополнительных ресурсов из-за большого количества вызовов функции пакета, которые необходимы (по одному вызову на каждую затрагиваемую строку). Эта специфическая проблема производительности исчезла, когда в Oracle 8.1 появились "переменные среды" и вызов sys_context().

С этой версии, если в вашем коде используются вызовы функции userenv(), вы должны стараться вместо нее использовать вызов sys_context() для контекста 'userenv'. Например:

select sys_context('userenv', 'sessionid') from dual;

вместо

select userenv('sessionid') from dual;

Функция userenv() является устаревшей, а контекст 'userenv'

имеет намного больше опций.


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