Почему не включается привилегированный режим в 1С 8.2/8.3 и как правильно обойти RLS в отчете?

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

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

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

Почему стандартный вызов УстановитьПривилегированныйРежим(Истина) не работает?

Давайте проанализируем типичную ситуацию. Разработчик в модуле объекта отчета пытается выполнить следующий код:


УстановитьПривилегированныйРежим(Истина);
Запрос.Текст = "ВЫБРАТЬ * ИЗ РегистрНакопления.Продажи";
Выборка = Запрос.Выполнить().Выбрать();
УстановитьПривилегированныйРежим(Ложь);

Несмотря на явный вызов метода, система все равно применяет ограничения RLS. Выделим три главные причины, почему это происходит:

  1. Ограничение контекста выполнения (Клиент против Сервера). В обычном приложении (Толстый клиент) код модуля объекта отчета по умолчанию выполняется на стороне клиента. В клиент-серверном варианте вызов метода УстановитьПривилегированныйРежим() на клиенте полностью игнорируется платформой. В файловом варианте этот метод технически доступен, но логика СУБД инициализирует ограничения прав в рамках сеанса пользователя, и полноценный обход RLS на клиенте часто не срабатывает.
  2. Ошибочное использование процедур-оберток (Время жизни режима). Попытка вынести включение режима в отдельную общую процедуру — одна из самых распространенных ошибок. Рассмотрим пример:
    
    Процедура ВключитьРежим() Экспорт
        УстановитьПривилегированныйРежим(Истина);
    КонецПроцедуры
    

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

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

Перейдем к практическим решениям, которые помогут нам обойти эти ограничения.

Способ А. Полный перенос выполнения запроса в привилегированный общий модуль

Это самый надежный и архитектурно правильный способ. Чтобы привилегированный режим гарантированно сработал, код запроса должен выполняться на сервере внутри специального модуля.

Давайте по шагам разберем процесс реализации этого механизма:

  1. Создание общего модуля. В конфигураторе добавьте новый общий модуль (например, с именем ОбщегоНазначенияПривилегированный).
  2. Настройка свойств модуля. В палитре свойств созданного модуля установите следующие флаги:
    • Клиент (обычное приложение) — выключено (чтобы гарантировать выполнение кода на сервере);
    • Сервер — включено;
    • Вызов сервера — включено;
    • Привилегированный — включено. При активации этого флага весь код внутри модуля по умолчанию выполняется с максимальными правами, и вызывать метод УстановитьПривилегированныйРежим() вручную больше не требуется.
  3. Размещение кода запроса. Перенесите логику формирования запроса в экспортную функцию общего модуля:
    
    Функция ПолучитьДанныеПродажБезRLS(ПараметрыЗапроса) Экспорт
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   Продажи.Номенклатура КАК Номенклатура,
            |   Продажи.Количество КАК Количество,
            |   Продажи.Стоимость КАК Стоимость
            |ИЗ
            |   РегистрНакопления.Продажи КАК Продажи
            |ГДЕ
            |   Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода";
            
        Запрос.УстановитьПараметр("НачалоПериода", ПараметрыЗапроса.НачалоПериода);
        Запрос.УстановитьПараметр("КонецПериода", ПараметрыЗапроса.КонецПериода);
        
        Возврат Запрос.Выполнить().Выгрузить(); // Возвращаем Таблицу значений
    КонецФункции
    
  4. Вызов функции из отчета. В модуле объекта вашего отчета вызовите созданную функцию общего модуля:
    
    Процедура ПередЗаполнением()
        ПараметрыЗапроса = Новый Структура;
        ПараметрыЗапроса.Вставить("НачалоПериода", НачПериода);
        ПараметрыЗапроса.Вставить("КонецПериода", КонПериода);
        
        // Получаем данные без учета RLS
        ТаблицаДанных = ОбщегоНазначенияПривилегированный.ПолучитьДанныеПродажБезRLS(ПараметрыЗапроса);
        
        // Дальнейшая обработка полученной таблицы значений на клиенте
    КонецПроцедуры
    

При таком подходе СУБД выполняет запрос под учетной записью администратора системы, полностью игнорируя настройки прав доступа текущего пользователя, после чего готовый результат в виде таблицы значений безопасно возвращается в контекст отчета.

Способ Б. Программный вывод отчета СКД на сервере

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

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

Выполним следующие шаги для настройки программного вывода:

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

Используя этот метод, вся цепочка генерации макета, выполнения запросов СКД к базе данных и заполнения результирующего табличного документа переносится на сервер. Проверки RLS для всех наборов данных схемы компоновки будут полностью отключены, и пользователь получит отчет со всеми необходимыми данными.

Важное предупреждение: Принудительное отключение RLS с помощью привилегированного режима накладывает на разработчика дополнительную ответственность. Убедитесь, что выводимые конфиденциальные данные не станут доступны пользователям, не имеющим на это законных бизнес-прав, вне рамок данного конкретного отчета.

← На главную