Новое в 8i: полномочия предъявителя в PL/SQL

Владимир Пржиялковский

Версия 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 добавляет разработчику не одну , а две дополнительные возможности для построения архитектуры программной системы: кроме возможности использования чистой модели полномочий создавшего (как раньше) появляется и возможность использования чистой модели полномочий предъявителя, и возможность комбинированного использования обеих моделей. Последний вариант - самый неоднозначный в плане конкретной реализации, так как теоретически охватывает все возможные комбинации разделения/обобществления (в "центральной" схеме) данных и разделения/обобществления кода. Выбор из этого множества конкретной комбинации для своей задачи должен быть сделан разработчиком взвешенно и ответственно.


Страница сайта http://www.interface.ru
Оригинал находится по адресу http://www.interface.ru/home.asp?artId=3783