Как привязать два файла default.vrd к одной базе 1С и настроить раздельную авторизацию для HTTP-сервисов в Apache

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешними платформами (например, сервисами доставки, маркетплейсами или платежными шлюзами) разработчики часто сталкиваются со специфическим требованием к протоколу авторизации. Внешняя система требует наличия единого базового адреса для всех запросов, но при этом протокол разделен на два этапа:

  1. Запрос на получение токена: метод (например, security/oauth/token), на который внешний сервис отправляет логин и пароль в теле сообщения или специальных параметрах без передачи стандартных заголовков HTTP-аутентификации. Этот эндпоинт должен быть доступен веб-серверу без запроса логина и пароля пользователя 1С.
  2. Запросы к бизнес-методам: все остальные вызовы, которые передают полученный токен доступа (обычно в заголовке Authorization: Bearer) и должны жестко контролироваться платформой или кодом конфигурации.

Выясним причину возникающей сложности. Параметры подключения к информационной базе в файле публикации default.vrd задаются глобально в строке подключения атрибута ib корневого элемента point. Если мы прописываем туда служебного пользователя через параметры Usr и Pwd, то все без исключения сервисы опубликованной базы перестают требовать аутентификацию на уровне веб-сервера. Если же убрать пользователя из default.vrd, модуль расширения веб-сервера 1С будет возвращать ошибку 401 Unauthorized еще до того, как управление будет передано в код метода HTTP-сервиса. Рассмотрим подробнее, какими способами можно обойти это ограничение и сохранить единый корень адреса публикации.

Решение 1. Настройка перекрывающихся директив Alias в конфигурации Apache

Разберем по шагам наиболее практичный способ решения задачи средствами веб-сервера Apache без привлечения дополнительного программного обеспечения. Идея заключается в публикации двух каталогов с независимыми файлами default.vrd и сопоставлении их с URL с помощью директив Alias в файле конфигурации httpd.conf.

Для реализации этого подхода создадим два каталога публикации на сервере:

  1. Каталог основной публикации (например, C:/inetpub/wwwroot/MyBase), где файл default.vrd содержит строку подключения без логина и пароля Usr и Pwd.
  2. Каталог авторизационной публикации (например, C:/inetpub/wwwroot/MyBase_Auth), где в файле default.vrd явно указаны служебный пользователь и пароль информационной базы.

Проанализируем работу директивы Alias в Apache. Модуль сопоставления путей просматривает список правил сверху вниз и применяет первое совпавшее правило. Поэтому критически важно соблюдать правильный порядок: более длинный, специфичный URL должен располагаться выше, чем общий базовый путь базы.

Посмотрим на пример фрагмента конфигурации httpd.conf:


# 1. Специфичный путь для точки получения токена (ведет к default.vrd с логином и паролем)
Alias "/MyBase/hs/YandexEda/security/oauth" "C:/inetpub/wwwroot/MyBase_Auth"
<Directory "C:/inetpub/wwwroot/MyBase_Auth">
    AllowOverride None
    Options None
    Require all granted
    SetHandler 1c-application
</Directory>

# 2. Общий базовый путь для всех остальных запросов (ведет к default.vrd без параметров Usr/Pwd)
Alias "/MyBase" "C:/inetpub/wwwroot/MyBase"
<Directory "C:/inetpub/wwwroot/MyBase">
    AllowOverride None
    Options None
    Require all granted
    SetHandler 1c-application
</Directory>

Когда внешний сервис обращается по адресу /MyBase/hs/YandexEda/security/oauth/token, Apache сопоставляет запрос с первым правилом и обращается к файлу default.vrd из каталога MyBase_Auth. Пользователь входит в 1С под служебной учетной записью, отрабатывает код метода и возвращает токен. Когда же приходит запрос на адрес /MyBase/hs/YandexEda/nomenclature/composition, первое правило не срабатывает, запрос перенаправляется во вторую директорию и обрабатывается стандартными механизмами проверки прав.

Важное замечание: Обратите внимание на значение атрибута base в файле default.vrd авторизационной директории. Модуль 1С сопоставляет входящие шаблоны HTTP-сервисов относительно значения base. Чтобы маршрутизация внутри 1С не возвращала ошибку 404, значение base должно соответствовать алиасу, назначенному в веб-сервере.

Решение 2. Подстановка авторизационного заголовка через mod_headers в Apache

Если нет желания создавать две отдельные публикации и дублировать каталоги, рассмотрим изящный альтернативный способ: автоматическое внедрение учетных данных веб-сервером через модуль mod_headers.

В этом сценарии информационная база публикуется один раз без сохранения пароля в default.vrd. Для запросов к точке авторизации Apache сам добавляет заголовок Basic-аутентификации перед передачей запроса модулю 1С. Разберем по шагам настройку:

  1. Убедимся, что в httpd.conf включен модуль LoadModule headers_module modules/mod_headers.so.
  2. Сформируем строку учетных данных в формате Base64 для служебного пользователя, например, для пары ServiceUser:SecretPassword закодированная строка будет иметь вид U2VydmljZVVzZXI6U2VjcmV0UGFzc3dvcmQ=.
  3. Ограничим подстановку заголовка с помощью блока <Location> только для адреса получения токена.

Посмотрим на пример конфигурации:


<Location "/MyBase/hs/YandexEda/security/oauth">
    RequestHeader set Authorization "Basic U2VydmljZVVzZXI6U2VjcmV0UGFzc3dvcmQ="
</Location>

В этом случае внешний клиент отправляет чистый запрос без заголовков авторизации, Apache на лету внедряет заголовок Authorization, платформа 1С успешно авторизует вызов под служебной учетной записью, а все прочие адреса сервиса остаются защищенными.

Решение 3. Использование обратного прокси-сервера (Nginx)

В архитектуре корпоративных систем часто используется подход с выносом маршрутизации на обратный прокси-сервер (Nginx или OpenResty), расположенный перед Apache или внутренним веб-сервером. Это позволяет гибко настраивать адресацию, отрезать служебные префиксы /hs/ и терминировать SSL-сертификаты.

При таком подходе в 1С создаются две обычные независимые публикации с разными именами, например /MyBase_Public и /MyBase_Auth, а внешний единый интерфейс конфигурируется в Nginx:


server {
    listen 443 ssl;
    server_name mysite.ru;

    # Маршрутизация метода получения токена на открытую публикацию
    location /MyBase/hs/YandexEda/security/oauth {
        proxy_pass http://127.0.0.1:8080/MyBase_Auth/hs/YandexEda/security/oauth;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Маршрутизация остальных вызовов на защищенную публикацию
    location /MyBase/ {
        proxy_pass http://127.0.0.1:8080/MyBase_Public/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Решение 4. Штатная аутентификация токенами доступа (JWT) в платформе 1С

Начиная с версии платформы 8.3.21, в 1С реализован нативный механизм валидации токенов доступа на уровне веб-сервера. Это избавляет от необходимости вручную парсить токены в каждом обработчике или создавать сложные схемы с раздельными публикациями.

Проанализируем порядок настройки штатного механизма:

  1. В свойствах пользователя информационной базы, под которым должны выполняться бизнес-запросы, устанавливаем флаг Аутентификация токеном доступа.
  2. В файле default.vrd внутри описания сервиса определяем параметры проверки токена с помощью блока accessTokenAuthentication, указав имя сервиса в качестве получателя и параметры доверенного эмитента:
    
    <httpServices>
        <service name="YandexEda">
            <accessTokenAuthentication>
                <accessTokenRecepientName>YandexEdaService</accessTokenRecepientName>
                <issuers>
                    <issuer issuerName="My1CAuthServer"
                            authenticationClaimName="sub"
                            authenticationUserPropertyName="name">
                        <keyInformation>СекретныйКлючПодписи</keyInformation>
                    </issuer>
                </issuers>
            </accessTokenAuthentication>
        </service>
    </httpServices>
    
  3. В методе HTTP-сервиса, отвечающем за выдачу токена, генерируем подписанный токен с использованием встроенного объекта платформы ТокенДоступа.

Посмотрим на пример генерации токена в коде 1С:


Токен = Новый ТокенДоступа;
Токен.Эмитент = "My1CAuthServer";
Токен.Получатели.Добавить("YandexEdaService");
Токен.ИмяПользователя = "ИнтеграцияЯндекс";
Токен.ВремяЖизни = 3600; // 1 час

СекретныйКлюч = Новый ЗащищенноеХранилищеОписанияКлюча("СекретныйКлючПодписи");
СтрокаТокена = Токен.Подписать(АлгоритмПодписиТокенаДоступа.HS256, СекретныйКлюч);

При таком подходе метод получения токена может быть открытым, а проверка валидности входящих запросов с заголовком Authorization: Bearer выполняется веб-сервером автоматически еще до обращения к прикладному коду.

Оптимизация пула сеансов для HTTP-сервисов

При использовании анонимных публикаций или автоматической подстановки служебного пользователя важно правильно настроить повторное использование сеансов в default.vrd. По умолчанию каждый входящий HTTP-запрос может инициировать запуск нового фонового сеанса, что быстро приведет к исчерпанию клиентских лицензий 1С.

Чтобы избежать захвата лишних лицензий, в элемент point файла default.vrd необходимо добавить параметры пула сеансов:


<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       base="/MyBase"
       ib="Srvr=Server1C;Ref=MyBase;"
       reuseSessions="autouse"
       sessionMaxAge="60"
       poolSize="10">

Атрибут reuseSessions="autouse" разрешает платформе повторно использовать освободившиеся сеансы того же пользователя, poolSize ограничивает максимальное число одновременно удерживаемых сеансов, а sessionMaxAge определяет время их удержания в секундах при отсутствии входящих запросов.

← На главную