При интеграции различных систем с платформой 1С через COM-соединение разработчики часто сталкиваются с неприятной особенностью: попытка вызвать метод УстановитьПривилегированныйРежим(Истина) внутри сеанса внешнего соединения не дает никакого результата. Функция ПривилегированныйРежим() упорно возвращает Ложь, а операции, требующие повышенных прав (например, чтение защищенных регистров или запись документов в обход RLS), завершаются ошибками доступа.
В этой статье мы подробно разберем, почему платформа «1С:Предприятие» ведет себя подобным образом, как устроена физика контекстов выполнения при COM-подключении и какими способами можно безопасно решить эту задачу, не нарушая общую безопасность системы.
---
Для начала давайте разберемся, почему обычный вызов привилегированного режима «зависает» или игнорируется платформой. Секрет кроется в архитектуре компиляции модулей 1С и понятии «клиентского окружения».
Когда внешнее приложение инициализирует подключение через объект V83.COMConnector, на стороне вызывающей операционной системы запускается внутрипроцессный COM-сервер (библиотека comcntr.dll). С точки зрения платформы 1С этот сеанс является разновидностью клиента (клиентским приложением), очень близким по своей сути к обычному или тонкому клиенту.
Рассмотрим, что происходит с общими модулями, у которых установлены флаги «Сервер» и «Внешнее соединение»:
rphost), другую — для выполнения на стороне клиента (в процессе comcntr.dll).COMСоединение.ИмяМодуля.ВыполнитьДействие()), этот код по умолчанию начинает выполняться **на стороне клиента** (в контексте внешнего соединения).УстановитьПривилегированныйРежим() игнорируется. Платформа 1С из соображений безопасности жестко блокирует повышение прав на стороне клиента, так как клиентское окружение считается потенциально небезопасным и подверженным модификации.Таким образом, даже если в настройках общего модуля установлен флаг «Сервер», фактического перехода выполнения кода на сервер приложений 1С не происходит, так как платформа находит локальную «клиентскую» копию этого модуля внутри запущенной библиотеки COM-соединения.
---
Самый правильный и безопасный архитектурный подход — принудительно заставить платформу выполнить перенос контекста (вызов сервера) с клиента на сервер приложений 1С. Сделать это напрямую через COM-объект невозможно, но мы можем использовать «модуль-обертку».
Разберем этот механизм по шагам. Создадим два общих модуля с разными свойствами компиляции.
Шаг 1. Создаем общий модуль-обертку (например, ИнтеграцияВнешнийВызов)
В свойствах этого модуля устанавливаем следующие флаги:
Этот модуль будет выступать точкой входа для нашего COM-соединения. Пропишем в нем вызов основного рабочего метода:
Процедура ВыполнитьДействиеИзВнешнегоИсточника(Параметры) Экспорт
// Данный код выполняется в контексте внешнего соединения (на клиенте).
// Передаем управление в чисто серверный модуль для смены контекста:
СерверныеОбработчикиИнтеграции.ВыполнитьДействиеНаСервере(Параметры);
КонецПроцедуры
Шаг 2. Создаем рабочий серверный модуль (например, СерверныеОбработчикиИнтеграции)
В свойствах этого модуля устанавливаем настройки:
Также для этого модуля можно установить признак «Привилегированный», чтобы права повышались автоматически, либо управлять режимом программно.
Поскольку у модуля СерверныеОбработчикиИнтеграции отсутствует флаг «Внешнее соединение», его код физически не может быть скомпилирован на стороне клиента COM. Платформа будет вынуждена выполнить удаленный вызов процедуры (RPC) на сервере приложений 1С.
Пропишем в рабочем модуле следующий код:
Процедура ВыполнитьДействиеНаСервере(Параметры) Экспорт
// Здесь мы гарантированно находимся на сервере приложений 1С (rphost)
УстановитьПривилегированныйРежим(Истина);
Если ПривилегированныйРежим() Тогда
// Выполняем действия, требующие обхода ограничений прав (RLS)
ЗаписатьРезультатВБазу(Параметры);
Иначе
ВызватьИсключение "Не удалось установить привилегированный режим!";
КонецЕсли;
КонецПроцедуры
Используя такую двухзвенную схему, мы гарантируем безопасный переход в серверный контекст, в котором привилегированный режим отрабатывает без каких-либо ограничений.
---
Если вам требуется, чтобы абсолютно все действия, производимые в рамках данного сеанса внешнего соединения, выполнялись под полными правами без необходимости доработки конфигурации, можно использовать специальный параметр строки подключения.
Параметр prmod=1 (Privileged Mode) принудительно переводит весь сеанс внешнего соединения в привилегированный режим с момента авторизации.
Рассмотрим пример строки подключения для файлового варианта базы данных:
СтрокаПодключения = "File=""C:\Base1C""; Usr=""ПользовательИнтеграции""; Pwd=""Пароль""; prmod=1;";
COMСоединение = Новый COMОбъект("V83.COMConnector");
БазаДанных = COMСоединение.Connect(СтрокаПодключения);
Для клиент-серверного варианта строка подключения будет выглядеть следующим образом:
СтрокаПодключения = "Srvr=""Server1C""; Ref=""TradeBase""; Usr=""ПользовательИнтеграции""; Pwd=""Пароль""; prmod=1;";
Важное предупреждение: Данный способ следует применять с крайней осторожностью. Использование параметра prmod=1 фактически нивелирует все настройки прав доступа (роли, RLS) для подключающегося пользователя. Любые действия, выполненные через это COM-соединение, будут иметь неограниченный доступ к базе данных, что может создать серьезную уязвимость в безопасности информационной системы.
---
Еще один надежный способ выполнить код на стороне сервера под привилегированным режимом — запуск фонового задания из контекста COM-соединения.
Фоновые задания в клиент-серверной архитектуре всегда запускаются и выполняются исключительно на сервере приложений 1С (в контексте менеджера кластера или рабочих процессов). Это значит, что внутри фонового задания привилегированный режим всегда доступен.
Проанализируем пример кода, выполняемого на стороне COM-клиента для запуска фонового задания:
// Внешнее соединение инициирует выполнение задания
МетодДляЗапуска = "СерверныеОбработчикиИнтеграции.ВыполнитьДействиеНаСервере";
ПараметрыЗапуска = Новый Массив;
ПараметрыЗапуска.Добавить(ПараметрыИнтеграции);
Задание = ФоновыеЗадания.Выполнить(МетодДляЗапуска, ПараметрыЗапуска);
// Ожидаем завершения работы задания на сервере
Задание.ОжидатьЗавершения(60);
Если Задание.Состояние = СостояниеФоновогоЗадания.Выполнено Тогда
// Задание завершено успешно, считываем результаты (например, из временного хранилища)
КонецЕсли;
Преимуществом данного метода является полная изоляция процесса выполнения. Даже если сеанс COM-соединения работает под сильно ограниченными правами, фоновое задание отработает на сервере с необходимым уровнем привилегий.
---
Подводя итоги нашего анализа интеграционных механизмов, выделим ключевые правила работы с привилегированным режимом во внешнем соединении:
УстановитьПривилегированныйРежим(Истина) в общих модулях, которые одновременно доступны для внешнего соединения и сервера, без явного вызова серверного контекста. Платформа выполнит этот код локально на клиенте, и режим не включится.prmod=1 только в исключительных случаях, когда конфигурация закрыта для редактирования, а безопасность внешнего источника полностью гарантирована вашим сетевым периметром.