Встраивание внешнего UI через фрейм
В данной статье на примере ОС Ubuntu 20 и сервиса Roundcube описан процесс добавления в панель любого своего контента, размещенного на внешних ресурсах, в виде фреймов - как веб-страницы внутри веб-страницы панели.
Добавление нового пункта меню
-
В папке /usr/local/mgr5/etc/xml создайте файл ispmgr_mod_testframe.xml со следующим содержимым:
<?xml version="1.0" encoding="UTF-8"?> <mgrdata> <mainmenu level="admin+"> <modernmenu> <node name="my_group"> <node name="testframe" /> </node> </modernmenu> </mainmenu> <handler name="testframe.sh" type="xml"> <func name="testframe" /> </handler> <lang name="ru"> <messages name="desktop"> <msg name="modernmenu_my_group">Test</msg> <msg name="modernmenu_testframe">Test Form Frame</msg> </messages> </lang> </mgrdata>
Пояснения:Таким образом в левом меню панели создается группа с названием Test, в ней пункт меню Test form frame, также в данном файле задается обработчик. -
Создайте файл-обработчик testframe.sh, добавьте в него следующие строчки:
#!/bin/bash cat /usr/local/mgr5/addon/testframe.xml
Это простейший обработчик, который возвращает статичное содержимое файла testframe.xml
- Поместите файл testframe.sh в папку /usr/local/mgr5/addon/ и дайте стандартные для обработчиков плагинов права:
chmod 755 testframe.sh
-
testframe.xml - XML-описание формы, поместите его в /usr/local/mgr5/addon/ рядом с предыдущим файлом.
<?xml version="1.0" encoding="UTF-8"?> <doc lang="ru" func="testframe" binary="/ispmgr"> <metadata name="testframe" type="form" mgr="ispmgr"> <form> <field name="frame" fullwidth="yes"> <frame name="roundcubeframe" forcetheme="yes" fullpage="yes" keepalive="yes" /> </field> </form> </metadata> <messages name="testframe" checked="6b49a92f5cc5153c76b78446d0d74eb4"> <msg name="title">Test Form Frame</msg> <msg name="frame">Frame</msg> </messages> <roundcubeframe>https://x.x.x.x:1501/roundcube/?_task=mail&_mbox=INBOX</roundcubeframe> </doc> где x.x.x.x - ip-адрес вашей панели
-
Перезагрузите панель командой в консоли:
killall core
После этого внизу левого меню должна появиться новая группа, в ней пункт меню Test Form Frame.
Дополнительные настройки
- Откройте файл testframe.xml на редактирование и исправьте ip-адрес в URL, указанном внутри тэга <roundcubeframe>, заменив его на ip-адрес своей панели. Все, кроме ip-адреса (протокол, порт, путь к Roundcube) можно оставить как есть.
- После редактирования и сохранения файла XML-описания формы перезапускать панель не требуется.
- Для корректной работы формы необходимо разрешить показывать Roundcube в чужом фрейме - по умолчанию он разрешает показывать себя только во фреймах с совпадающим хостом и портом (в данном случае порт отличается - у панели по умолчанию порт 1500, у Roundcube, который ставится с панелью ispmanager - порт 1501).
Есть 2 способа это сделать:
- Отключение заголовка
X-Frame-Options
в конфигурационном файлеRoundcube
- Перейдите в папку /etc/roundcube и откройте на редактирование файл config.inc.php
- В конце файла добавьте
строчку:
$config['x_frame_options'] = '';
- С этой опцией Roundcube перестанет добавлять дефолтное значение SAMEORIGIN для заголовка X-Frame-Options. Изменение начнет действовать сразу после сохранения файла config.inc.php, ничего перезагружать не нужно.
- настройка заголовка
Content-Security-Policy
Использование заголовка
X-Frame-Options
позволяет задать только две опции, которые либо вообще запрещают показ контента во фрейме, либо разрешают показ только во фрейме с того же хоста и порта. Для того, чтобы наш контент был виден только в фрейме с какого-то другого хоста или порта, нужно использовать заголовокContent-Security-Policy
.- Отключите заголовок
X-Frame-Options
, который по умолчанию добавляет Roundcube (см. инструкцию в предыдущем разделе) - Перейдите в папку /etc/nginx/vhosts-includes и откройте на редактирование файл
roundcube-nginx.conf
В секции, начинающейся со строки
location ~ ^/roundcube/(.+\.php)$ {
, а также в секции, начинающейся со строкиlocation ~* ^/roundcube/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
добавьте строку:add_header "Content-Security-Policy" "frame-ancestors x.x.x.x:1500"; *** Замените x.x.x.x:1500 на ip-адрес и порт вашей панели
- Для активации изменений перезагрузите nginx командой
/etc/init.d/nginx restart
Настройка заголовка
Content-Security-Policy
в ApacheВо многих случаях для показа контента во фрейме может потребоваться настроить заголовок **
Content-Security-Policy
** в веб-сервере Apache. В конфигурационный файл Apache соответствующего уровня (это может быть.htaccess
для конкретной папки или конфигурационные файлы в/etc/apache2
или/etc/httpd
- на ваше усмотрение) потребуется добавить следующий код, заменив хост и порт на используемые панелью:<IfModule mod_headers.c> Header set Content-Security-Policy "frame-ancestors 172.31.97.115:1500" </IfModule>
- Отключите заголовок
- Отключение заголовка
Опции фрейма
Для тега <frame> могут быть использованы следующие атрибуты:
keepalive
- этот атрибут позволяет сохранить состояние фрейма при переключении на другие вкладки панели и последующем возврате на вкладку фрейма;fullheight
- заставляет фрейм растягиваться до нижней границы окна браузера;fullpage
- заставляет фрейм растягиваться от левого меню и полосы в шапке панели до нижней и правой границы окна браузера, таким образом заполняя все место, которое занимала форма;forcetheme
- этот атрибут при отображении фрейма в панели со включенной темной темой применяет фильтр к контенту фрейма, пытаясь подстроить его цвета под темную тему панели. В зависимости от страницы или приложения, отображаемого во фрейме, использование этого атрибута может быть полезным или наоборот нежелательным.
"yes"
Пример использования атрибутов <frame>:
<frame name="frame" forcetheme="yes" fullpage="yes" keepalive="yes" />
Этот фрейм будет растягиваться на все окно, кроме левого меню и шапки панели, будет сохраняться при переходе на другие вкладки панели и в темной теме пытаться подстроиться под цвета панели.
Внутри описания формы мы помещаем тэг <frame> внутри тэга <field>, задавая нужное имя фрейма (name="roundcubeframe") и описанные выше атрибуты.
URL страницы, отображаемой во фрейме, нужно добавить внутри тэга <doc> как тэг, совпадающий по названию с именем фрейма в описании формы <roundcubeframe>:
https://ip-адрес:1501/roundcube/?_task=mail&_mbox=INBOX</roundcubeframe>