При разработке интеграционных решений в среде «1С:Предприятие 8» (особенно в крупных ERP-системах) часто возникает необходимость запускать внешние отчеты или обработки программным путем. Одной из распространенных проблем при таком подходе является внезапный сбой механизмов интеграции, например, при вызове веб-сервисов. В процессе выполнения кода система генерирует неинформативное сообщение: «Ошибка при вызове конструктора (WSОпределения)». При этом, если запустить тот же отчет интерактивно через меню «Файл — Открыть», все работает без нареканий.
В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем внутренние механизмы платформы, управляющие безопасностью, и рассмотрим несколько вариантов решения проблемы — от быстрого «обходного пути» до архитектурно правильного использования Библиотеки стандартных подсистем (БСП).
Для начала проанализируем исходную ситуацию. Разработчик программно извлекает двоичные данные внешней обработки (отчета) из справочника ДополнительныеОтчетыИОбработки, записывает их во временный файл на сервере и создает объект обработки следующим образом:
ОбработкаСсылка = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоРеквизиту("ИмяОбъекта", ИмяОбъекта);
ДвоичныеДанныеОбработки = ОбработкаСсылка.ХранилищеОбработки.Получить();
ДвоичныеДанныеОбработки.Записать(ИмяВременногоФайлаОбработки);
ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ИмяВременногоФайлаОбработки);
После создания объекта вызывается его экспортный метод, внутри которого происходит инициализация веб-сервиса через Новый WSОпределения. Именно на этой строке код завершается аварийно.
Главная причина кроется в поведении метода платформы ВнешниеОбработки.Создать(). По умолчанию, когда данный метод вызывается в серверном контексте (особенно внутри модулей HTTP-сервисов, Web-сервисов или фоновых заданий), платформа 1С запускает загружаемый внешний код в безопасном режиме.
Безопасный режим накладывает на исполняемый код жесткие ограничения в целях защиты системы от деструктивных действий. В безопасном режиме платформой полностью блокируются:
Поскольку конструктор WSОпределения пытается выполнить сетевой запрос к WSDL-схеме стороннего ресурса, платформа расценивает это как нарушение политики безопасности и мгновенно прерывает выполнение операции. При этом функция регистрации СведенияОВнешнейОбработке(), в которой разработчик мог указать ПараметрыРегистрации.БезопасныйРежим = Ложь, при ручной записи во временный файл полностью игнорируется, так как она используется БСП только на этапе интерактивной регистрации обработки администратором.
Самый простой способ вернуть работоспособность коду — явно указать платформе, что внешнюю обработку необходимо запустить без ограничений безопасного режима. Для этого обратимся к синтаксису метода Создать() менеджера внешних обработок:
Создать(<ПолноеИмяФайла>, <БезопасныйРежим>, <ЗащитаОтОпасныхДействий>)
Обратите внимание на второй параметр. Если мы не передаем его, платформа может принудительно выставить значение Истина. Передадим туда значение Ложь в явном виде:
// Явно отключаем безопасный режим при создании объекта обработки
ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ИмяВременногоФайлаОбработки, Ложь);
Этот способ мгновенно решает проблему: сетевой доступ для обработки открывается, и конструктор WSОпределения успешно инициализируется.
Важное предупреждение о безопасности: Полное отключение безопасного режима несет серьезные риски. Если код внешней обработки будет изменен злоумышленником или загружен из ненадежного источника, он получит неограниченный доступ к серверу (сможет удалять файлы, вызывать сторонние утилиты ОС и передавать конфиденциальные данные). Кроме того, если на сервере 1С настроены жесткие профили безопасности кластера, вызов метода с параметром Ложь может быть заблокирован самой платформой на уровне настроек администрирования.
Для того чтобы не изобретать велосипед с записью временных файлов и ручным вызовом низкоуровневых методов платформы, воспользуемся штатным программным интерфейсом Библиотеки стандартных подсистем (БСП). В БСП заложен безопасный и контролируемый механизм программного подключения внешних объектов.
Рассмотрим, как правильно переписать исходный код инициализации обработки:
// 1. Получаем имя, под которым БСП временно регистрирует обработку в текущей сессии.
// Метод автоматически учитывает настройки безопасности, заданные в карточке справочника.
ИмяОбработки = ДополнительныеОтчетыИОбработки.ПодключитьВнешнююОбработку(ОбработкаСсылка);
// 2. Создаем объект обработки стандартным менеджером платформы, используя полученное имя
ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ИмяОбработки);
// 3. Безопасно вызываем необходимую команду
ВнешняяОбработкаОбъект.ВыполнитьКоманду(ИмяВыполняемойКоманды, ПараметрыКоманды);
При использовании метода ПодключитьВнешнююОбработку() БСП самостоятельно считывает настройки безопасного режима прямо из карточки элемента справочника Дополнительные отчеты и обработки. Если в карточке указано, что обработка должна запускаться в небезопасном режиме, БСП применит этот параметр автоматически без ручного написания временных файлов.
Если ваша конфигурация работает во фреше (облаке) или в корпоративной среде с жестким контролем безопасности, полное отключение безопасного режима неприемлемо. В этом случае мы можем оставить безопасный режим включенным (БезопасныйРежим = Истина), но точечно запросить у системы разрешение на обращение к конкретному адресу веб-сервиса.
Для этого в модуле объекта внешней обработки внутри функции СведенияОВнешнейОбработке() необходимо явно описать требуемые разрешения:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
ПараметрыРегистрации.Вид = ПолучитьВидОбработки();
// ... заполнение остальных параметров ...
// Оставляем безопасный режим включенным
ПараметрыРегистрации.БезопасныйРежим = Истина;
// Создаем массив для хранения точечных разрешений
МассивРазрешений = Новый Массив;
// Описываем параметры целевого веб-сервиса
Протокол = "https";
АдресСервера = "api.external-system.ru";
Порт = 443;
// Запрашиваем разрешение на сетевой доступ к конкретному ресурсу
Разрешение = РаботаВБезопасномРежиме.РазрешениеНаИспользованиеИнтернетРесурса(Протокол, АдресСервера, Порт);
МассивРазрешений.Добавить(Разрешение);
ПараметрыРегистрации.Разрешения = МассивРазрешений;
Возврат ПараметрыРегистрации;
КонецФункции
При интерактивной регистрации или обновлении такой обработки в интерфейсе ERP администратору системы будет выведено понятное окно с запросом на предоставление доступа к конкретному адресу api.external-system.ru. После одобрения обработка сможет выполнять вызов WSОпределения к этому серверу, оставаясь при этом в безопасном режиме для всех остальных операций (например, она по-прежнему не сможет читать произвольные локальные файлы сервера 1С).
Поскольку в рассматриваемом сценарии вызов происходит из модуля HTTP-сервиса, важно помнить об особенностях выполнения серверного неинтерактивного кода:
Создать() третьим параметром следует передавать отключение предупреждений защиты. Сделать это можно с помощью функции БСП: ВнешниеОбработки.Создать(Путь, Ложь, ОбщегоНазначения.ОписаниеЗащитыБезПредупреждений()).Проанализировав все три способа, мы рекомендуем использовать Решение №2 в связке с Решением №3 для достижения максимального уровня стабильности и информационной безопасности вашей системы.