Как запустить внешний отчет в привилегированном режиме для обхода ограничений RLS?

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

При работе с типовыми конфигурациями на обычных формах (например, 1С:Управление производственным предприятием 1.3) разработчики часто сталкиваются с ситуацией, когда внешний отчет должен выводить данные, скрытые от пользователя настройками RLS (Record Level Security — ограничение доступа на уровне записей). Стандартный механизм выполнения внешних отчетов в безопасном режиме блокирует возможность использования привилегированного режима. В этой статье мы подробно разберем, как обойти это ограничение и заставить отчет работать с полными данными без изменения ролей пользователей.

Понимание проблемы: Безопасный режим и RLS

Проанализируем, почему обычный вызов команды УстановитьПривилегированныйРежим(Истина) внутри модуля внешнего отчета не приносит результата. По умолчанию платформа 1С запускает внешние обработки и отчеты в так называемом безопасном режиме. В этом режиме игнорируются любые попытки программного перехода в привилегированный режим. Это сделано для безопасности, чтобы вредоносный код из внешнего файла не смог получить несанкционированный доступ к данным или выполнить опасные операции на сервере.

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

Способ 1: Программный запуск с отключением безопасного режима

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

Посмотрим на пример кода, который позволяет создать объект отчета без ограничений безопасности:


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

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

Чтобы этот способ заработал в типовой системе, нам придется внести небольшие изменения в конфигурацию. Нужно найти место, где происходит программное создание объекта внешнего отчета, и добавить условие или параметр, который будет передавать Ложь в метод Создать. После этого в модуле самого отчета можно будет смело писать:


Процедура ПриОткрытии()
    УстановитьПривилегированныйРежим(Истина);
    // Теперь запросы будут игнорировать RLS
КонецПроцедуры

Способ 2: Использование привилегированного общего модуля

Если мы не хотим или не можем менять механизм запуска внешних отчетов в справочнике, разберем второй вариант — вынос запроса в общий модуль конфигурации. Этот метод считается более "чистым" с точки зрения архитектуры, так как контроль безопасности остается на стороне конфигурации.

Выполним следующие шаги:

  1. Создадим в конфигурации новый общий модуль (или используем существующий).
  2. В свойствах модуля установим флаги Сервер и Привилегированный. Флаг Привилегированный означает, что весь код в этом модуле будет выполняться с полными правами, игнорируя RLS.
  3. Напишем в модуле экспортную функцию, которая выполняет запрос и возвращает результат в виде таблицы значений.

Пример кода в общем модуле МойПривилегированныйМодуль:


Функция ПолучитьДанныеДляОтчета(ПараметрыЗапроса) Экспорт
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ * ИЗ РегистрНакопления.Продажи ГДЕ Организация = &Организация";
    Запрос.УстановитьПараметр("Организация", ПараметрыЗапроса.Организация);
    
    Возврат Запрос.Выполнить().Выгрузить();
КонецФункции

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

Способ 3: Использование фоновых заданий

Проанализируем еще один интересный метод, который не требует изменения типовых справочников и хорошо подходит для клиент-серверного варианта работы. Фоновые задания по умолчанию выполняются на сервере в привилегированном режиме (если не задано иное).

Мы можем инициировать выполнение запроса через фоновое задание. Выясним, как это реализовать:

  1. Внешний отчет вызывает процедуру, которая запускает фоновое задание.
  2. Фоновое задание собирает данные (без учета RLS) и помещает их во ВременноеХранилище.
  3. Основной поток отчета ожидает завершения задания, забирает таблицу из хранилища и выводит пользователю.

Этот способ позволяет обойти ограничения, даже если отчет запущен в безопасном режиме, так как само выполнение запроса происходит в другом контексте (в контексте фонового задания на сервере).

Способ 4: Расширения конфигурации (для платформы 8.3)

Если ваша УПП 1.3 работает на современной платформе (8.3.6 и выше), мы можем воспользоваться механизмом расширений. Это позволит нам не трогать основную конфигурацию, сохраняя её на поддержке.

Создадим расширение и добавим в него привилегированный общий модуль. Внешний отчет сможет обращаться к процедурам этого модуля точно так же, как к родным модулям конфигурации. Это наиболее современный и безопасный подход, так как изменения локализованы внутри расширения.

Важные нюансы работы с СКД в привилегированном режиме

Рассмотрим специфику работы Системы компоновки данных. Даже если вы отключили безопасный режим и установили привилегированный режим, СКД может продолжать учитывать RLS при автоматическом исполнении запроса. Выясним причину: это происходит потому, что процессор компоновки может инициализироваться с проверкой прав доступа.

Для гарантированного обхода RLS в СКД рекомендуется программная инициализация компоновки в модуле объекта отчета:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    // Устанавливаем привилегированный режим в начале формирования
    УстановитьПривилегированныйРежим(Истина);
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры

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

Заключение и выбор метода

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

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

← На главную