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