СТАТЬЯ
15.01.02

<< Часть 3

Детальный контроль доступа и контексты приложения (Часть 4)

© Том Кайт
Статья была опубликована в журнале OracleMagazine

Теперь присоединимся различными пользователями и протестируем функциональность приложения.

SQL> @rls_adams
SQL> -- Присоединимся как служащий, у которого нет способности управлять.
SQL> connect rls_adams/rls_adams
Connected.
SQL> set serveroutput on
SQL> -- Сначала попробуем стать менеджером
SQL> -- Мы не являемся менеджером, поэтому стать им
SQL> -- не разрешается
SQL> exec rls.set_role( 'mgr' )
BEGIN rls.set_role( 'mgr' ); END;
*
ERROR at line 1:
ORA-20002: Вы не менеджер
ORA-06512: at "RLS.SET_ROLE", line 53
ORA-06512: at line 1

Таким образом, результат показывает, что нельзя получить роль, не предназначенную для текущего пользователя. Чтобы убедиться, что ни к каким данным нет доступа, попробуем теперь запросить что-нибудь, и посмотрим, что произойдет:

SQL> -- теперь посмотрим, что произойдет при попытке выполнить
SQL> -- что-нибудь без получения роли
SQL> exec rls.hr_app.listEmps
------ КонтекстСессии ----------
HR_APP_CTX.EMPNO = 7876
------ Данные таблицы Emp, которые можно увидеть -----
BEGIN rls.hr_app.listEmps; END;
*
ERROR at line 1:
ORA-28112: ошибка при выполнении функции политики
ORA-06512: at "RLS.HR_APP", line 18
ORA-06512: at line 1

Появилось сообщение об ошибке. Это сообщение возникло, потому что так написана предикатная функция:

function select_function( p_schema in varchar2,
                         p_object in varchar2 ) return varchar2
is
begin
    if ( g_sel_pred is NULL )
   then
        if ( sys_context( g_app_ctx, 'RoleName' ) = 'EMP' )
 
       then
           …
 
       elsif ( sys_context( g_app_ctx, 'RoleName' ) = 'MGR' )
 
       then

 
       elsif ( sys_context( g_app_ctx, 'RoleName' ) = 'HR_REP' )
 
       then

 
       else
 
           raise_application_error( -20005, 'Рольнеустановлена' );
       end if;

   end if;
    return g_sel_pred;
end;

Полученный результат - это результат выполнения raise_application_error в предикатной функции. Конечный пользователь получает сообщение об ошибке ORA-28112. Далее, в следующей секции, мы рассмотрим, как обнаружить эти ошибки и отладить их.

Далее установим такую роль, чтобы можно было что-нибудь сделать, и попробуем выполнить эти же операции:

SQL> -- Теперь установим корректную роль и выполним что-нибудь
 SQL> exec rls.set_role( 'emp' );
PL/SQL procedure successfully completed.
SQL> -- посмотрим контекст и данные,
SQL> -- которые можно видеть - это только одна запись
SQL> exec rls.hr_app.listEmps
------ КонтекстСессии ----------
HR_APP_CTX.ROLENAME = EMP
HR_APP_CTX.EMPNO = 7876
------ Данные таблицы Emp, которые можно увидеть -----
RLS_ADAMS,1100,RESEARCH
PL/SQL procedure successfully completed.
 SQL> -- несмотря на то, что данные "видно" 
SQL> -- их нельзя "изменить".
SQL> exec rls.hr_app.updateSal
0 rows updated
PL/SQL procedure successfully completed.
SQL> -- нельзя удалить никакую информацию
 SQL> exec rls.hr_app.deleteAll
0 rows deleted
PL/SQL procedure successfully completed.
SQL> -- нельзя ничего создать
SQL> exec rls.hr_app.insertNew(20)
BEGIN rls.hr_app.insertNew(20); END;
*
ERROR at line 1:
ORA-28115: нарушение политики с опцией проверки
ORA-06512: at "RLS.HR_APP", line 44
ORA-06512: at line 1

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

Далее присоединимся как MGR и посмотрим, что произойдет:

SQL> -- Присоединимся как менеджер
SQL> connect rls_jones/rls_jones
Connected.
SQL> -- Включим возможность вывода на экран из PL/SQL
SQL> set serveroutput on
SQL> -- Для начала попробуем стать менеджером
SQL> -- мы являемся менеджером, так как на этот раз нам разрешено
SQL> -- статьим
SQL> exec rls.set_role( 'mgr' )
PL/SQL procedure successfully completed.
SQL> -- посмотрим контекст и данные,
SQL> -- которые можно видеть. На этот раз - более одной строки.
SQL> exec rls.hr_app.listEmps
------ КонтекстСессии ----------
HR_APP_CTX.ROLENAME = MGR
HR_APP_CTX.EMPNO = 7566
------ Данные таблицы Emp, которые можно увидеть -----
RLS_SMITH,800,RESEARCH
RLS_JONES,2975,RESEARCH
RLS_SCOTT,3000,RESEARCH
RLS_ADAMS,1100,RESEARCH
RLS_FORD,3000,RESEARCH
PL/SQL procedure successfully completed.
SQL> -- Следующая операция показывает, что некоторые записи можно 
SQL> -- изменить. Затем снова выполним listEmps для того, чтобы увидеть,
SQL> -- какие строки изменились (только те, которые подчинены напрямую)
SQL> exec rls.hr_app.updateSal
2 rows updated
 PL/SQL procedure successfully completed.
 SQL> exec rls.hr_app.listEmps
------ КонтекстСессии ----------
HR_APP_CTX.ROLENAME = MGR
HR_APP_CTX.EMPNO = 7566
------ Данные таблицы Emp, которые можно увидеть -----
RLS_SMITH,800,RESEARCH
RLS_JONES,2975,RESEARCH
RLS_SCOTT,9999,RESEARCH
RLS_ADAMS,1100,RESEARCH
RLS_FORD,9999,RESEARCH
PL/SQL procedure successfully completed.
SQL> -- так как мы не являемся контролером, то, 
SQL> -- согласно заданным правилам, нельзя никого удалить
SQL> exec rls.hr_app.deleteAll
0 rows deleted
PL/SQL procedure successfully completed.
SQL> -- так как мы не являемся контролером, то, 
SQL> -- согласно заданным правилам, нельзя никого вставить
SQL> exec rls.hr_app.insertNew(20)
BEGIN rls.hr_app.insertNew(20); END;
*
ERROR at line 1:
ORA-28115: нарушение политики с опцией проверки
ORA-06512: at "RLS.HR_APP", line 44
ORA-06512: at line 1

Таким образом, теперь нам, как MGR, можно:

И, наконец, присоединимся как контролер и посмотрим на поведение приложения при работе с этой ролью:

SQL> -- Присоединимся как контролер
SQL> connect rls_king/rls_king
Connected.
SQL> -- Подключим возможность вывода на экран из PL/SQL
SQL> set serveroutput on
SQL> -- Для начала, попробуем стать контролером
SQL> -- Теперь мы являемся контролером, так как
SQL> -- стать им разрешено
SQL> exec rls.set_role( 'hr_rep' )
PL/SQL procedure successfully completed.
SQL> -- посмотрим контекст и данные,
SQL> -- которые можно видеть.  На этот раз видно все строки, так как
SQL> -- пользователь - контолер.
SQL> exec rls.hr_app.listEmps
------ КонтекстСессии ----------
HR_APP_CTX.ROLENAME = HR_REP
HR_APP_CTX.EMPNO = 7839
------ Данные таблицы Emp, которые можно увидеть -----
RLS_CLARK,2450,ACCOUNTING
RLS_KING,5000,ACCOUNTING
RLS_MILLER,1300,ACCOUNTING
RLS_SMITH,800,RESEARCH
RLS_JONES,2975,RESEARCH
RLS_SCOTT,9999,RESEARCH
RLS_ADAMS,1100,RESEARCH
RLS_FORD,9999,RESEARCH
RLS_ALLEN,1600,SALES
RLS_WARD,1250,SALES
RLS_MARTIN,1250,SALES
RLS_BLAKE,2850,SALES
RLS_TURNER,1500,SALES RLS_JAMES,950,SALES
PL/SQL procedure successfully completed.
SQL> -- следующая операция показывает, что можно изменить любую запись
SQL> -- в любом отделе, так как пользователь для всех
SQL> -- является контролером
SQL> -- далее снова запустим listEmps, чтобы увидеть, какие
SQL> -- строки изменились (все)
SQL> exec rls.hr_app.updateSal
14 rows updated
PL/SQL procedure successfully completed.
SQL> -- так как пользователь - контролер, то он может
SQL> -- удалить кого-нибудь согласно заданным правилам
SQL> -- При удалении ВСЕХ не удаляется 'я',
SQL> -- т.е. текущий пользователь
SQL> exec rls.hr_app.deleteAll
13 rows deleted
PL/SQL procedure successfully completed.
SQL> -- так как пользователь - контролер, то он может 
SQL> -- вставить кого-нибудь согласно заданным правилам
SQL> exec rls.hr_app.insertNew(20)
PL/SQL procedure successfully completed.
SQL> -- посмотрим на результат изменения, удаления
SQL> -- и последующей вставки
SQL> exec rls.hr_app.listEmps
------ КонтекстСессии ----------
HR_APP_CTX.ROLENAME = HR_REP
HR_APP_CTX.EMPNO = 7839
------ Данные таблицы Emp, которые можно увидеть -----
RLS_KING,9999,ACCOUNTING
,1111,RESEARCH
PL/SQL procedure successfully completed.

На этом завершается тестирование трех ролей рассматриваемого примера. Все требования удовлетворены - безопасность данных обеспечена, и они стали прозрачными для приложения.

Обработка ошибок и отладка

Во время создания вышеописанного приложения я натолкнулся на некоторые ошибки и должен был его отлаживать. Так как детальный контроль доступа работает на сервере, то при обнаружении ошибок и отладке приложения могут возникнуть сложности. Следующий раздел поможет успешной отладке и обнаружению ошибок.

Во время разработки процедур детального контроля доступа могут появиться четыре основных кода ошибок Oracle:

При написании предикатных функций я часто пользуюсь одной утилитой - это пакет ‘debug’. Этот пакет, автором которого является Кристофер Бек (Christopher Beck) из Oracle, позволяет вставить в код предложения команду ‘print’. Кроме того, этот пакет позволяет широко использовать предложения типа:

create function foo …
as
 
  …
begin
 
    debug.f( ‘Входвпроцедуру foo’ );
 
    if ( some_condition ) then
 
        l_predicate := ‘x=1’;
 
    end if; 
     debug.f( ‘Переходквозвратупредиката "%s"’, l_predicate );
 
    return l_predicate;
end;

Таким образом, работа процедуры debug.f похожа на с-функцию printf, а сама она использует пакет UTL_FILE. На сервере базы данных она создает управляемые программистом файлы трассировки. Файлы трассировки содержат отладочные предложения, которые можно использовать для просмотра выполненных действий при выполнении кода. Так как программный код находится в ядре базы данных, отладка может оказаться сложной. Наличие файлов трассировки может сэкономить много времени. Скрипты, которые можно загрузить (см. далее в этом же разделе) содержат отладочный пакет и комментарии по его установке и использованию.

“За” и “Против”

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

За

Против

Упрощает разработку приложения – переносит управление доступом из приложения на уровень данных.

 

Отладка может оказаться сложной, так как детальный контроль доступаосуществляется в фоновом режиме. Для этой цели более подходят пакеты типа ‘debug’, о которых идет речь в секции диагностики и отладки.

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

 

Допускает значительные изменения политики безопасности без влияния на клиентские приложения.

 

Упрощает управление объектами базы данных. Уменьшается общее число объектов базы данных, необходимых для поддержки приложения.

 

Хорошо работает. Использование контекстов приложения позволяет воспользоваться преимуществами разделяемого SQL.

 

Скрипты

Для того, чтобы получить все скрипты, используемые в этой статье, загрузите tar-файл. Пожалуйста, непременно прочитайте файл README.TXT, входящий в состав архива. Tar-файл можно открыть под Windows с помощью WinZip версии 6.0 и выше.

Дополнительную информацию Вы можете получить в компании Interface Ltd.

Обсудить на форуме Oracle
Отправить ссылку на страницу по e-mail


Interface Ltd.
Тel/Fax: +7(095) 105-0049 (многоканальный)
Отправить E-Mail
http://www.interface.ru
Ваши замечания и предложения отправляйте автору
По техническим вопросам обращайтесь к вебмастеру
Документ опубликован: 15.01.02