При разработке приложений в APEX часто нужны разные уровни доступа для пользователей – например, когда приложением пользуются юзеры из разных подразделений, или когда нужно создать отчеты, видимые только админам.
Доступ к объектам приложения управляется через схемы авторизации (Authorization Schemes), которые находятся в Shared Components приложения.
Не нужно путать авторизацию и аутентификацию в APEX. Схемы аутентификации управляют доступом пользователей к приложению (возможностью залогиниться), а авторизации – доступом к определенным объектам приложения.
Аутентификация находится за рамками данной статью, но про нее уже есть хороший материал.
Одним из вариантов разграничения доступа, то есть внедрения ролевой модели, может быть постраничная авторизация – это схема, при которой явно указываются страницы, доступные для каждого пользователя (или роли).
Рассмотрим для примера приложение, в котором есть два отчета – Admin Report и User Report и пользователи– ADMIN, USER1 и USER2.
Нужно сделать так, чтобы ADMIN видел все страницы, а USER’ы не видел Admin Report.
1. Определение ролевой модели
Для начала, нужно определиться, как будет выглядеть ролевая модель: для небольших приложений имеет смысл определять список доступных страниц напрямую для каждого пользователя, но если в приложении много страниц или пользователей, удобнее будет ввести роли и сделать две связки "пользователь -> роль" и "роль -> страница", то есть каждому пользователю присвоить роль, и для каждой роли настроить доступ к определенным страницам.
Мы пойдем по второму пути, так как ожидаем, что в последствие число пользователей вырастет.
Введем две роли ADMIN и USER и создадим таблицу USER_ROLE
и таблицу ROLE_PAGE
Как видим, для роли USER не указан доступ к странице 2.
Номера страниц можно посмотреть в Application Builder в APEX или через представления APEX в БД:
select *
from APEX_APPLICATION_PAGES
where APPLICATION_ID = <номер вашего приложения>
2. Создание схемы авторизации
Теперь напишем функцию, принимающую на вход имя пользователя и страницу приложения возвращающую булевое значение, есть ли доступ у данного пользователя для данной страницы.
create or replace function PAGE_AUTH (p_user in varchar2,
p_page_id in number)
return boolean
as
l_cnt number;
begin
select count(*) into l_cnt
from USER_ROLE ur
join ROLE_PAGE rp on ur.user_role = rp.user_role
where upper(p_user)=upper(ur.user_name)
and p_page_id = rp.page_id;
if l_cnt > 0 then
return TRUE;
else return FALSE;
end if;
end PAGE_AUTH;
В приложении APEX создадим новую схему авторизации. В Shared components -> Authorization Schemes нажимаем на кнопку “Сreate” и указываем “From scratch”. Выбираем имя схемы, указываем созданную выше функцию и выбираем “Validate one per page view”:
3. Выбор схемы авторизации
Теперь нужно выбрать созданную схему для данного приложения. Для этого идем в Shared components -> User Interface Attributes (блок User Interface). В разделе Security ->Authorization выбираем созданную схему и жмем “Apply Changes”.
Поздравляем, вы только что создали постраничную схему авторизации!
Теперь при попытке USER1 и USER2 посмотреть Admin Report они будут видеть следующее:
4. Изменение навигационного меню (Navigation Menu)
Если страницы в приложении привязаны к объектам навигационного меню, то все эти объекты останутся видимыми для всех пользователей, поскольку авторизация привязана к страницам, а не к пунктом навигационного меню (Navigation Menu List Entries). То есть пользователи USER1и USER2 будут видеть в навигации Admin Report, не смотря на то, что при нажатии на него будут получать ошибку доступа.
Можно оставить и такую реализацию, но лучше скрыть от пользователей из меню те страницы, на которые они все равно не могут перейти.
Для того, чтобы пользователи видели навигационное меню в зависимости от своего уровня доступа нужно перейти от статического навигационного меню по умолчанию к динамическому.
Смысл в том, чтобы взять объекты статического меню (обычно называется 'Desktop Navigation Menu'), посмотреть, с какими страницами связаны его объекты, и с использованием созданной ролевой модели, показывать пользователю только те List Entries, которые связаны с доступными ему страницами.
Воспользуемся APEX представлением (view) APEX_APPLICATION_LIST_ENTRIES, в котором есть информация, какие страницы прикреплены к каким объектам навигации. Для того, чтобы не поддерживать отдельно еще одну таблицу со связью Роль -> Объект навигации, создадим представление, связывающее роли и List Entries на основе связи Роль –> Страница:
SET DEFINE OFF;
CREATE OR REPLACE EDITIONABLE VIEW ROLE_LIST_ENTRY ("USER_ROLE", "LIST_ENTRY_ID") AS
select distinct p.user_role, l.list_entry_id
from apex_application_list_entries l
join role_page p on l.entry_target like 'f?p=&APP_ID.:'||p.page_id||':&%SESSION%' or entry_target is null
where l.list_name = 'Desktop Navigation Menu'
and l.application_id = <номер вашего приложения>;
Если сделать select из созданного представления, то можно увидеть, что для роли ADMIN доступны 3 list entry, а для USER – только 2:
Пришло время сделать динамическое навигационное меню. Для этого в Shared Components -> Navigation Menu создаем новое меню: выбираем “From scratch” и Dynamic, в появившееся окно SQL запроса вписываем следующее:
select level, al.entry_text label, al.entry_target
from apex_application_list_entries al
join ROLE_LIST_ENTRY rl on al.list_entry_id = rl.list_entry_id
join USER_ROLE ur on ur.user_role = rl.user_role and upper(ur.user_name) = upper(:APP_USER)
where
al.LIST_NAME = 'Desktop Navigation Menu'
and al.application_id = <номер вашего приложения>
start with al.list_entry_parent_id is null
connect by prior al.list_entry_id = al.list_entry_parent_id
order siblings by al.display_sequence
Теперь нужно выбрать Динамическое навигационное меню для нашего интерфейса. Для этого опять переходим в Shared Components -> User Interface Attributes. В разделе User Interface нажимаем на значок редактирования текущего интерфейса и попадаем в User Interface Details. Во вкладке Navigation Menu выбираем созданное нами меню и жмем “Apply Changes”
Теперь USER1 и USER2 при входе в приложение не будут видеть в меню навигации Audit Report:
Схемы авторизации необходимы для больших приложений, постраничная авторизация отличается простотой поддержки и хорошей масштабируемостью – при создании новых страниц и добавлении новых пользователей нужно только добавить соответствующие наблюдения в USER_ROLE и ROLE_PAGE, для чего можно сделать соответствующие формы в самом приложении (и не забыть указать роль администратора для этих форм).
Другие статьи на тему APEX:
- Установка и конфигурирование Oracle Application Express 5 (APEX) и Oracle REST Data Services 3 (ORDS) для сервера приложений Weblogic 12
- Создание домена в weblogic 12с и запуск его как службы Windows
- Настройка доменной аутентификации в Oracle Apex
- Как настроить постраничную авторизацию в Oracle APEX
- Подключение схемы (таблицы) в Oracle Application Express 5 (APEX)
- Создание приложения в Oracle Application Express 5 (APEX)
- Перенос APEX приложения из среды разработки в продуктовую среду