При интеграции 1С со сторонними сервисами и веб-приложениями часто возникает требование отказаться от стандартной Basic-авторизации (логин и пароль в заголовке Authorization) в пользу передачи API-ключа (например, в заголовке X-API-Key или параметрах URL). Однако разработчики сталкиваются с жестким ограничением платформы 1С: модуль расширения веб-сервера (модули wsap24.dll для Apache или wsisapi.dll для IIS) перехватывает входящие запросы еще до передачи управления во встроенный язык. Если в запросе отсутствует заголовок Basic-авторизации, веб-расширение сразу возвращает ответ с кодом 401 Unauthorized, и код обработчика HTTP-сервиса просто не вызывается.
Если же прописать логин и пароль в строке соединения файла default.vrd, то перестает нормально работать авторизация интерактивных пользователей: тонкий и веб-клиенты начинают автоматически заходить под этой технической учетной записью. Разберем, как обойти это ограничение и организовать надежную авторизацию по API-ключу.
Оптимальным и штатным решением является создание двух независимых публикаций одной и той же информационной базы на веб-сервере:
/workbase, в файле default.vrd не содержит сохраненных учетных данных. Пользователи тонких и веб-клиентов входят под своими персональными логинами и паролями./workbase_api), где отключен клиентский доступ, прописан сервисный пользователь с минимальными правами, а HTTP-сервисы принимают анонимные запросы от внешних систем.Рассмотрим по шагам реализацию этой схемы.
Для интеграции создаем отдельного пользователя в списке пользователей информационной базы:
api_user) и надежный пароль.Для сервисной публикации создаем отдельный каталог на сервере (например, C:\inetpub\wwwroot\workbase_api или /var/www/workbase_api) и формируем в нем файл default.vrd.
Разберем ключевые параметры, которые необходимо настроить в дескрипторе публикации:
<point> указываем атрибут enable="false". Это полностью блокирует запуск клиентских приложений через этот путь.ib строки подключения жестко прописываем логин и пароль созданного пользователя.standardOdata и ws (SOAP веб-сервисы).publishByDefault="false" и выборочно разрешаем только нужные сервисы.reuseSessions="autouse" и sessionMaxAge="20". Без этого на каждый HTTP-запрос будет создаваться отдельный сеанс, что быстро исчерпает свободные лицензии.Посмотрим на пример итогового файла default.vrd для клиент-серверной базы:
<?xml version="1.0" encoding="UTF-8"?>
<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="/workbase_api"
ib="Srvr=server1c;Ref=workbase;Usr=api_user;Pwd=SecretPass123;"
enable="false">
<standardOdata enable="false"/>
<ws enable="false"/>
<httpServices publishByDefault="false">
<service name="ИнтеграцияAPI"
rootUrl="integration"
enable="true"
reuseSessions="autouse"
sessionMaxAge="20"/>
</httpServices>
</point>
Для файловой информационной базы строка ib примет следующий вид:
ib="File="D:\bases\workbase";Usr=api_user;Pwd=SecretPass123;"
В конфигурационном файле веб-сервера (например, httpd.conf для Apache) можно объявить неограниченное количество алиасов, указывающих на разные каталоги с файлами default.vrd. Платформа 1С позволяет также выполнить публикацию через командную строку утилитой webinst, указав разные имена путей через параметр -wsdir:
webinst -publish -apache24 -wsdir workbase_api -dir "C:\inetpub\wwwroot\workbase_api" -connstr "Srvr=server1c;Ref=workbase;Usr=api_user;Pwd=SecretPass123;" -confpath "C:\Apache24\conf\httpd.conf"
Так как входящий запрос успешно прошел веб-расширение под служебной учетной записью, управление передается в метод HTTP-сервиса. Теперь мы можем извлечь токен и выполнить его проверку.
Разберем пример обработчика метода HTTP-сервиса, проверяющего ключ в заголовке X-API-Key:
Функция ДанныеGET(Запрос)
// Извлекаем токен из заголовков запроса
ПереданныйКлюч = Запрос.Заголовки.Получить("X-API-Key");
// Если токен не передан в заголовках, пробуем проверить параметры URL
Если Не ЗначениеЗаполнено(ПереданныйКлюч) Тогда
ПереданныйКлюч = Запрос.ПараметрыЗапроса.Получить("api_key");
КонецЕсли;
// Сверяем полученный ключ с эталоном (например, из константы или регистра сведений)
ЭталонныйКлюч = Константы.КлючДоступаAPI.Получить();
Если Не ЗначениеЗаполнено(ПереданныйКлюч) Или ПереданныйКлюч <> ЭталонныйКлюч Тогда
Ответ = Новый HTTPСервисОтвет(401);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоДляОбработки(Новый ДвоичныеДанныеИзСтроки("{\"error\": \"Неверный или отсутствующий API-ключ\"}"));
Возврат Ответ;
КонецЕсли;
// Основная бизнес-логика сервиса
СтруктураОтвета = Новый Структура("status", "success");
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураОтвета);
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоДляОбработки(Новый ДвоичныеДанныеИзСтроки(ЗаписьJSON.Закрыть()));
Возврат Ответ;
КонецФункции
Хранение пароля пользователя в открытом виде внутри файла default.vrd может не соответствовать строгим регламентам безопасности компании. В таких случаях между внешними клиентами и 1С устанавливается обратный прокси (например, Nginx).
Проанализируем принцип работы данной схемы:
default.vrd не прописывается.X-API-Key).Authorization: Basic <base64(user:password)> и перенаправляет запрос на порт веб-сервера 1С.Таким образом, разделение веб-публикаций или применение прокси-сервера позволяет полностью уйти от передачи Basic-авторизации на стороне клиентских систем, сохранив безопасность и работоспособность интерактивных пользователей.