div.main {margin-left: 20pt; margin-right: 20pt}
Новое в 8i: полномочия предъявителя в
PL/SQL
Владимир Пржиялковский 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), но при попытке работать с объектами БД –
таблицами, последовательностями – права на доступ к этим объектам в предыдущих
версиях соответствовали полномочиям создателя процедуры. (Сейчас это верно
только по умолчанию, если специально не оговорить другую схему работы). Вот
некоторые свойства такой модели полномочий:
все внешние ссылки в программе должны быть разрешены на этапе трансляции с
помощью прямой передачи полномочий пользователю, от имени которого
транслируется программа
имеющиеся роли на этапе трансляции не действуют
права на доступ к объектам БД на этапе выполнения процедуры полностью
совпадают с правами пользователя-создателя процедуры
хотя “транслирующий” пользователь и должен иметь полномочия на работу с
используемыми в процедуре объектами, пользователь, вызывающий программу, иметь
такие полномочия не обязан Такая логика работы имеет определенные
преимущества. Вот, примерно, как их формулировали в фирме Oracle:
Такая модель позволяет улучшить контроль работы с данными. Работу с
таблицей можно организовать так, что изменение ее содержимого станет
пользователям Oracle возможно только посредством обращения к определенным
процедурам.
Процедуры работают быстро, потому что не тратят время на проверку прав
доступа во время исполнения.
Разработчик не должен беспокоиться о том, что может быть ненамеренно
модифицирована не та таблица – все объекты жестко
предопределены.Звучит разумно. Проблемы с
полномочиями создавшего
Тем не менее, 90% разработчиков сознаются, что использование модели
“полномочий создавшего” доставляет им непрерывную головную боль из-за
необходимости придумывать специальные ухищрения, в конечном счете негативно
сказывающиеся на архитектуре создаваемой системы.
Вот типичный случай. Пусть создается система по схеме “центр –
территориальные отделения”. Все территориальные отделения (ТО) однородны по сути
и работают с одними и теми же программами, но каждое со своими собственными
данными. Пусть все обслуживается одним сервером БД (например, работа идет через
Internet). Тогда логично (и правильно с точки зрения безопасности и
разграничения доступа) дать каждому ТО по самостоятельному имени в БД и по
отдельной схеме данных. Другое дело, что схемы эти будут у всех одинаковы. И
одинаковым должен быть код программ, работающих с данными.
Для кода напрашивается (логически правильное) решение: создать отдельную
схему БД, скажем, с именем COMMON, и в ней создавать сами PL/SQL-пакеты и
процедуры. Но как ими будут пользоваться ТО ? Обратиться к процедуре просто
new_employee ТО не может, так как процедура ему не принадлежит. Обратиться
COMMON.new_employee тоже нельзя, потому что схема COMMON не владеет данными
вызывающего ТО, а кроме того помещать в код приложения имя схемы тоже не всегда
правильно.
Прежде в таких ситуациях приходилось копировать пакеты из COMMON в схемы ТО
(см. рисунок) – во многих отношениях не лучшее решение, но часто единственно
приемлемое.
Полномочия предъявителя
Синтаксис указания полномочий предъявителя чрезвычайно прост: в заголовке
процедуры или функции перед словом IS или AS надо написать AUTHID CURRENT_USER.
(Соответственно появившееся вариантное указание AUTHID DEFINER вступает в силу
при отсутствии указаний). Модель прав предъявителя работает по следующим
правилам:
Для разрешения внешних ссылок при выполнении программы анализируются роли
пользователя, запустившего программу.
Предложение AUTHID можно использовать лишь в заголовках отдельных
программ, пакетов и спецификаций объектного типа. Предложение AUTHID нельзя
использовать в отдельных программах или методах из состава пакета или описания
типа объекта.
Вот перечень предложений, для которых права доступа проверяются
динамически во время исполнения программы:
SELECT, INSERT, UPDATE, DELETE
LOCK TABLE
OPEN и OPEN-FOR для курсоров
EXECUTE IMMEDIATE и OPEN-FOR-USING предложения динамического SQL
SQL-предложения, транслируемые программой
Внешние ссылки на PL/SQL-программы и методы объектов разрешаются во время
компиляции по правилам создавшего. Вот как примером разъясняет такое положение
дел Стивен Фойерштайн (применение предложения AUTHID CURRENT_USER выделено
серым фоном): /* Basic demonstration of AUTHID CURRENT_USER feature */
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 добавляет
разработчику не одну, а две дополнительные возможности для
построения архитектуры программной системы: кроме возможности использования
чистой модели полномочий создавшего (как раньше) появляется и возможность
использования чистой модели полномочий предъявителя, и возможность
комбинированного использования обеих моделей. Последний вариант – самый
неоднозначный в плане конкретной реализации, так как теоретически охватывает все
возможные комбинации разделения/обобществления (в “центральной” схеме) данных и
разделения/обобществления кода. Выбор из этого множества конкретной комбинации
для своей задачи должен быть сделан разработчиком взвешенно и ответственно.
|