Владимир Пржиялковский
16 февраля 2000 г.
Версия Oracle 8i (8.1), выпущенная в 1999 году после долгих задержек, содержит большой объем нововведений (как утверждает сама фирма, “более 150”). Многие из них коснулись такой базовой компоненты, как PL/SQL. Несмотря на появление у разработчика альтернативы в виде Java (говорят, в фирме Oracle долго спорили по поводу перспектив выбора языка программирования для системы, но, в конце концов, пришли к Соломонову решению), PL/SQL остается наиболее эффективным встроенным языком в Oracle, превосходя по своим возможностям аналоги конкурентов – Informix 4GL и Sybase/Microsoft Transact-SQL. Тем обиднее, что некоторые качества PL/SQL появляются только сейчас, в версии 8.1, а не были встроены 10 лет назад, в результате чего разработчики оказались лишены, казалось бы, естественных возможностей и тратили свои усилия на придумывание ухищрений, ныне лишенных смысла. Особенно обидно, когда речь идет о синтаксических конструкциях, исчерпывающихся всего парой слов, но меняющих, несмотря на это, значительную часть архитектуры создаваемого кода.
Одно из таких “микро-нововведений”, приближающих логику функционирования
кода на PL/SQL логике исполнения программ в Unix, рассмотрим сегодня. Речь
идет о так называемых “полномочиях предъявителя” (invoker rights) для процедур
на PL/SQL.
Полномочия создавшего, прежде единственные
В версиях 7 и 8.0 единственной логикой контроля доступа к объектам БД из процедуры на PL/SQL была логика “полномочия создавшего” (definer rights). Процедура всегда создается от какого-нибудь имени пользователя Oracle. Вызываться она может и другим пользователем (владеющим на это правом, данным с помощью предложения GRANT EXECUTE), но при попытке работать с объектами БД – таблицами, последовательностями – права на доступ к этим объектам в предыдущих версиях соответствовали полномочиям создателя процедуры. (Сейчас это верно только по умолчанию, если специально не оговорить другую схему работы). Вот некоторые свойства такой модели полномочий:
Тем не менее, 90% разработчиков сознаются, что использование модели “полномочий создавшего” доставляет им непрерывную головную боль из-за необходимости придумывать специальные ухищрения, в конечном счете негативно сказывающиеся на архитектуре создаваемой системы.
Вот типичный случай. Пусть создается система по схеме “центр – территориальные отделения”. Все территориальные отделения (ТО) однородны по сути и работают с одними и теми же программами, но каждое со своими собственными данными. Пусть все обслуживается одним сервером БД (например, работа идет через Internet). Тогда логично (и правильно с точки зрения безопасности и разграничения доступа) дать каждому ТО по самостоятельному имени в БД и по отдельной схеме данных. Другое дело, что схемы эти будут у всех одинаковы. И одинаковым должен быть код программ, работающих с данными.
Для кода напрашивается (логически правильное) решение: создать отдельную схему БД, скажем, с именем COMMON, и в ней создавать сами PL/SQL-пакеты и процедуры. Но как ими будут пользоваться ТО ? Обратиться к процедуре просто new_employee ТО не может, так как процедура ему не принадлежит. Обратиться COMMON.new_employee тоже нельзя, потому что схема COMMON не владеет данными вызывающего ТО, а кроме того помещать в код приложения имя схемы тоже не всегда правильно.
Прежде в таких ситуациях приходилось копировать пакеты из COMMON в схемы ТО (см. рисунок) – во многих отношениях не лучшее решение, но часто единственно приемлемое.
Полномочия предъявителя
Синтаксис указания полномочий предъявителя чрезвычайно прост: в заголовке процедуры или функции перед словом IS или AS надо написать AUTHID CURRENT_USER. (Соответственно появившееся вариантное указание AUTHID DEFINER вступает в силу при отсутствии указаний). Модель прав предъявителя работает по следующим правилам:
CONNECT demo/demo
CREATE PROCEDURE dummy1 IS
BEGIN
DBMS_OUTPUT.put_line ('Dummy1 owned by demo');
END;
/
GRANT execute on dummy1 to public;
CONNECT scott/tiger
CREATE PROCEDURE dummy1 IS
BEGIN
DBMS_OUTPUT.put_line ('Dummy1 owned by scott');
END;
/
GRANT execute on dummy1 to public;
CREATE PROCEDURE dummy2 AUTHID CURRENT_USER
IS
BEGIN
dummy1;
END;
/
GRANT execute on dummy2 to public;
EXEC scott.dummy2
CONNECT demo/demo
SET serveroutput on
EXEC scott.dummy2
Результаты вызова dummy2 от имени SCOTT и от имени DEMO разные.
Совсем по-другому будет выглядеть теперь схема использования программ территориальными отделениями (см. рисунок).
Какую модель когда использовать ?
Применение модели “полномочий предъявителя” возможно и в других ситуациях, помимо приведенной. Оно полезно, когда администратор (или кто-нибудь из разработчиков) создает программы общего назначения для всех пользователей. Вот еще одна простая иллюстрация из Стивена Фойерштайна:
CREATE OF REPLACE PROCEDURE runddl (ddl_in in VARCHAR2)
AUTHID CURRENT_USER
IS
BEGIN
EXECUTE IMMEDIATE ddl_in;
END;
/
EXECUTE IMMEDIATE – еще одно нововведение версии 8i, требующее особого
разговора; здесь же важно, что мы имеем возможность дать всем пользователям
общую и полезную процедуру, не утруждая себя кухней проверки прав. Вся
ответственность за корректное обращение с данными ложится на пользователя,
вызвавшего процедуру.
Но вернемся к перечню “преимуществ модели полномочий создавшего” выше.
Он не теряет своей актуальности, и отказываться от этой модели полностью
было бы неразумно. Очевидно, что несколько запоздалое нововведение Oracle
добавляет разработчику не одну, а две дополнительные возможности
для построения архитектуры программной системы: кроме возможности использования
чистой модели полномочий создавшего (как раньше) появляется и возможность
использования чистой модели полномочий предъявителя, и возможность комбинированного
использования обеих моделей. Последний вариант – самый неоднозначный в
плане конкретной реализации, так как теоретически охватывает все возможные
комбинации разделения/обобществления (в “центральной” схеме) данных и разделения/обобществления
кода. Выбор из этого множества конкретной комбинации для своей задачи должен
быть сделан разработчиком взвешенно и ответственно.
Литература
За дополнительной информацией обращайтесь в Interface Ltd.