При интеграции различных информационных баз 1С часто используется механизм COM-соединения. Одной из типичных проблем, с которой сталкиваются разработчики, является отказ работы метода УстановитьПривилегированныйРежим(Истина). Ситуация выглядит следующим образом: в целевой базе (База 2) написан код, который должен выполнять запрос в обход прав текущего пользователя, но при вызове этого кода из внешней базы (База 1) под пользователем с ограниченными правами возникает ошибка "Нарушение прав доступа". Рассмотрим подробно причины этого поведения и разберем способы решения задачи.
Метод УстановитьПривилегированныйРежим предназначен для временного отключения проверки прав доступа (RLS) и проверок на уровне объектов для текущего сеанса. Однако в контексте COM-соединения вступают в силу дополнительные ограничения платформы 1С:Предприятие, которые могут блокировать включение этого режима. Проанализируем основные причины, по которым это происходит.
Это наиболее частая причина. Если код, содержащий УстановитьПривилегированныйРежим(Истина), находится во внешней обработке, которая открывается через COM, платформа по умолчанию может запускать ее в безопасном режиме. В безопасном режиме метод установки привилегий просто игнорируется платформой без вызова исключения, но и без фактического отключения проверок прав.
Выясним, как это происходит. Если вы подключаетесь к базе и создаете объект внешней обработки программно:
// В Базе 1
Соединение = Новый COMОбъект("V83.COMConnector");
База2 = Соединение.Connect(СтрокаПодключения);
Обработка = База2.ВнешниеОбработки.Создать(ПутьКФайлу);
Обработка.ВыполнитьЗапрос();
В этом случае База2.ВнешниеОбработки.Создать без дополнительных параметров может инициализировать обработку в безопасном режиме. Чтобы этого избежать, необходимо передавать параметр БезопасныйРежим = Ложь, однако для этого у COM-пользователя должны быть административные права, что противоречит условию задачи (работа под пользователем с низкими правами).
Начиная с версии платформы 8.3.9, была введена защита от опасных действий. Если для пользователя, под которым осуществляется подключение, в базе-приемнике включен этот флаг, то выполнение потенциально опасных операций (включая работу с внешними модулями) будет заблокировано или ограничено. В COM-сессии интерактивное подтверждение невозможно, поэтому операция прерывается.
Рекомендация: Проверьте настройки пользователя в базе 1С:ЗУП 3 (или другой целевой конфигурации). В карточке пользователя на вкладке "Администрирование" можно временно отключить защиту от опасных действий для проверки гипотезы.
Проанализируем ситуацию с параметрами сеанса. При COM-подключении не отрабатывают стандартные обработчики начала работы системы, такие как ПриНачалеРаботыСистемы. Если ваши ограничения прав доступа (RLS) завязаны на параметры сеанса (например, ТекущийПользователь, СпискиПодразделений), и эти параметры не были инициализированы программно при старте COM-сессии, то даже в привилегированном режиме запрос может вернуть пустой результат или ошибку, так как условия RLS могут интерпретировать пустые параметры как жесткий запрет.
Самым надежным и правильным архитектурным решением является вынос критического кода в общий модуль на стороне базы-приемника. Рассмотрим пошагово, как это реализовать:
_ИнтеграцияВызовСервера).При использовании модуля с флагом "Привилегированный" нам даже не нужно вызывать УстановитьПривилегированныйРежим(Истина) внутри кода — весь код в таком модуле всегда выполняется с полными правами. Посмотрим на пример кода в общем модуле:
// В общем модуле Базы 2 (флаги: Сервер, Внешнее соединение, Привилегированный)
Функция ПолучитьДанныеДляИнтеграции(ПараметрыЗапроса) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Зарплата.Сотрудник,
| Зарплата.СуммаВзаиморасчетов
|ИЗ
| РегистрНакопления.ЗарплатаКВыплате КАК Зарплата";
// RLS не будет применяться, так как модуль привилегированный
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Теперь из Базы 1 вызов будет выглядеть максимально просто:
// Вызов из Базы 1
Результат = База2._ИнтеграцияВызовСервера.ПолучитьДанныеДляИнтеграции(Параметры);
Рассмотрим преимущества этого метода. Во-первых, вы избегаете проблем с безопасным режимом внешних обработок. Во-вторых, общий модуль компилируется при запуске сеанса COM и гарантированно имеет доступ к серверному контексту. В-третьих, это повышает безопасность системы: вы точно контролируете, какие именно действия разрешены низкоправному пользователю через COM, предоставляя ему доступ только к конкретной экспортной функции привилегированного модуля.
Посмотрим на различие между Сервером и Внешним соединением. Если вы пишете код внутри модуля обработки, убедитесь, что он не обернут в инструкции препроцессора типа #Если Клиент Тогда. COM-соединение не является клиентом в контексте управляемых форм, это отдельный тип соединения, который ближе всего к серверному, но имеет свои особенности компиляции (флаг "Внешнее соединение").
Также проанализируем совет из сообщения 10: com.execute(УстановитьПривилегированныйРежим(Истина)). Такой подход не сработает. Привилегированный режим устанавливается для конкретного потока выполнения (процедуры/функции) и сбрасывается автоматически при выходе из нее. Попытка установить его "снаружи" через объект COM-соединения не изменит права для последующих вызовов методов обработки.
Если у вас не отрабатывает УстановитьПривилегированныйРежим в COM-сессии: