Почему возникает ошибка конструктора WSОпределения при программном вызове внешнего отчета и как ее решить?

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

При разработке интеграционных решений в среде «1С:Предприятие 8» (особенно в крупных ERP-системах) часто возникает необходимость запускать внешние отчеты или обработки программным путем. Одной из распространенных проблем при таком подходе является внезапный сбой механизмов интеграции, например, при вызове веб-сервисов. В процессе выполнения кода система генерирует неинформативное сообщение: «Ошибка при вызове конструктора (WSОпределения)». При этом, если запустить тот же отчет интерактивно через меню «Файл — Открыть», все работает без нареканий.

В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем внутренние механизмы платформы, управляющие безопасностью, и рассмотрим несколько вариантов решения проблемы — от быстрого «обходного пути» до архитектурно правильного использования Библиотеки стандартных подсистем (БСП).

Выясняем причину: почему падает конструктор WSОпределения?

Для начала проанализируем исходную ситуацию. Разработчик программно извлекает двоичные данные внешней обработки (отчета) из справочника ДополнительныеОтчетыИОбработки, записывает их во временный файл на сервере и создает объект обработки следующим образом:


ОбработкаСсылка = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоРеквизиту("ИмяОбъекта", ИмяОбъекта);
ДвоичныеДанныеОбработки = ОбработкаСсылка.ХранилищеОбработки.Получить();
ДвоичныеДанныеОбработки.Записать(ИмяВременногоФайлаОбработки);
ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ИмяВременногоФайлаОбработки);

После создания объекта вызывается его экспортный метод, внутри которого происходит инициализация веб-сервиса через Новый WSОпределения. Именно на этой строке код завершается аварийно.

Главная причина кроется в поведении метода платформы ВнешниеОбработки.Создать(). По умолчанию, когда данный метод вызывается в серверном контексте (особенно внутри модулей HTTP-сервисов, Web-сервисов или фоновых заданий), платформа 1С запускает загружаемый внешний код в безопасном режиме.

Безопасный режим накладывает на исполняемый код жесткие ограничения в целях защиты системы от деструктивных действий. В безопасном режиме платформой полностью блокируются:

  1. Доступ к файловой системе сервера (кроме временных файлов).
  2. Использование привилегированного режима.
  3. Вызов внешних COM-объектов.
  4. Любые сетевые запросы и внешние соединения (включая HTTP, FTP и WS-соединения).

Поскольку конструктор WSОпределения пытается выполнить сетевой запрос к WSDL-схеме стороннего ресурса, платформа расценивает это как нарушение политики безопасности и мгновенно прерывает выполнение операции. При этом функция регистрации СведенияОВнешнейОбработке(), в которой разработчик мог указать ПараметрыРегистрации.БезопасныйРежим = Ложь, при ручной записи во временный файл полностью игнорируется, так как она используется БСП только на этапе интерактивной регистрации обработки администратором.

Решение №1: Быстрое отключение безопасного режима (с оговорками)

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

Создать(<ПолноеИмяФайла>, <БезопасныйРежим>, <ЗащитаОтОпасныхДействий>)

Обратите внимание на второй параметр. Если мы не передаем его, платформа может принудительно выставить значение Истина. Передадим туда значение Ложь в явном виде:


// Явно отключаем безопасный режим при создании объекта обработки
ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ИмяВременногоФайлаОбработки, Ложь);

Этот способ мгновенно решает проблему: сетевой доступ для обработки открывается, и конструктор WSОпределения успешно инициализируется.

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

Решение №2: Использование штатных механизмов БСП (Рекомендуется)

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

Рассмотрим, как правильно переписать исходный код инициализации обработки:


// 1. Получаем имя, под которым БСП временно регистрирует обработку в текущей сессии.
// Метод автоматически учитывает настройки безопасности, заданные в карточке справочника.
ИмяОбработки = ДополнительныеОтчетыИОбработки.ПодключитьВнешнююОбработку(ОбработкаСсылка);

// 2. Создаем объект обработки стандартным менеджером платформы, используя полученное имя
ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ИмяОбработки);

// 3. Безопасно вызываем необходимую команду
ВнешняяОбработкаОбъект.ВыполнитьКоманду(ИмяВыполняемойКоманды, ПараметрыКоманды);

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

Решение №3: Тонкая настройка разрешений в безопасном режиме (Best Practice)

Если ваша конфигурация работает во фреше (облаке) или в корпоративной среде с жестким контролем безопасности, полное отключение безопасного режима неприемлемо. В этом случае мы можем оставить безопасный режим включенным (БезопасныйРежим = Истина), но точечно запросить у системы разрешение на обращение к конкретному адресу веб-сервиса.

Для этого в модуле объекта внешней обработки внутри функции СведенияОВнешнейОбработке() необходимо явно описать требуемые разрешения:


Функция СведенияОВнешнейОбработке() Экспорт

    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
    ПараметрыРегистрации.Вид = ПолучитьВидОбработки();
    // ... заполнение остальных параметров ...
    
    // Оставляем безопасный режим включенным
    ПараметрыРегистрации.БезопасныйРежим = Истина;
    
    // Создаем массив для хранения точечных разрешений
    МассивРазрешений = Новый Массив;
    
    // Описываем параметры целевого веб-сервиса
    Протокол = "https"; 
    АдресСервера = "api.external-system.ru"; 
    Порт = 443;
    
    // Запрашиваем разрешение на сетевой доступ к конкретному ресурсу
    Разрешение = РаботаВБезопасномРежиме.РазрешениеНаИспользованиеИнтернетРесурса(Протокол, АдресСервера, Порт);
    МассивРазрешений.Добавить(Разрешение);
    
    ПараметрыРегистрации.Разрешения = МассивРазрешений;
    
    Возврат ПараметрыРегистрации;

КонецФункции

При интерактивной регистрации или обновлении такой обработки в интерфейсе ERP администратору системы будет выведено понятное окно с запросом на предоставление доступа к конкретному адресу api.external-system.ru. После одобрения обработка сможет выполнять вызов WSОпределения к этому серверу, оставаясь при этом в безопасном режиме для всех остальных операций (например, она по-прежнему не сможет читать произвольные локальные файлы сервера 1С).

Особенности выполнения кода в HTTP-сервисах

Поскольку в рассматриваемом сценарии вызов происходит из модуля HTTP-сервиса, важно помнить об особенностях выполнения серверного неинтерактивного кода:

Проанализировав все три способа, мы рекомендуем использовать Решение №2 в связке с Решением №3 для достижения максимального уровня стабильности и информационной безопасности вашей системы.

← На главную