Как ведет себя RLS в строке кода с выборкой через метод Выбрать()?

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

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

Суть проблемы: столкновение объектной техники и RLS

Рассмотрим стандартную ситуацию. У нас есть регистр сведений ЖурналОтчетовСтатусы, в котором настроено ограничение доступа по реквизиту Организация. Программист пытается получить данные, используя объектную технику:


Выборка = Вычислить("РегистрыСведений.ЖурналОтчетовСтатусы.Выбрать(Новый Структура(""Ссылка"", ОтчетСсылка))");
Если Выборка.Следующий() Тогда
    // Обработка данных
КонецЕсли;

Несмотря на то, что у пользователя есть права на чтение этого регистра, система выбрасывает исключение. Разберем по шагам, почему это происходит. Главное отличие заключается в том, как платформа интерпретирует методы объектов (справочников, документов, регистров) по сравнению с текстом запроса.

Режим «ВСЕ» против режима «РАЗРЕШЕННЫЕ»

Проанализируем ключевое различие. В языке запросов 1С мы можем явно указать слово РАЗРЕШЕННЫЕ. В этом случае платформа автоматически отфильтровывает те записи, на которые у пользователя нет прав согласно правилам RLS, и возвращает только доступные данные. Ошибки при этом не возникает, даже если часть данных скрыта.

Однако при использовании объектов встроенного языка, таких как СправочникМенеджер, РегистрСведенийМенеджер и их методов Выбрать(), СрезПоследних() или Получить(), ситуация иная. Все операции над объектами выполняются в режиме «ВСЕ». Это означает, что система пытается прочитать данные без неявного добавления фильтров по правам доступа в тело генерируемого SQL-запроса.

Если в результат выборки попадает хотя бы одна запись, не соответствующая условиям RLS, платформа не «проглатывает» эту ситуацию, а инициирует прерывание выполнения кода с ошибкой нарушения прав доступа. Это механизм «жесткой проверки», который гарантирует целостность бизнес-логики в объектной модели.

Как обеспечить успешное выполнение метода Выбрать()

Для того чтобы метод Выбрать() отработал без ошибок в условиях активного RLS, мы должны соблюсти критически важное условие: структура отбора в методе должна быть идентична или строже, чем условия в правилах ограничения доступа.

Рассмотрим пример. Если в настройках прав доступа (RLS) для регистра КонтактнаяИнформация прописано условие:

ГДЕ Тип = &ТипКонтактнойИнформации

Тогда следующий код приведет к ошибке:


// Ошибка! Система пытается получить ВСЕ записи, нарушая условие RLS
Срез = РегистрыСведений.КонтактнаяИнформация.СрезПоследних();

Чтобы исправить это, нам необходимо явно передать в отбор тот параметр, который ожидает RLS:


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

Сложные условия RLS и невозможность использования объектной техники

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

Поскольку параметр Отбор в методе Выбрать() принимает только простую структуру (соответствие «Реквизит = Значение»), мы физически не можем воспроизвести в ней сложную логику RLS. Если ограничение нельзя выразить простым равенством, метод Выбрать() всегда будет возвращать ошибку прав доступа при попытке прочитать данные, защищенные сложным правилом.

Альтернативные способы решения

Проанализируем, какие инструменты есть у разработчика, если стандартная выборка не работает.

  1. Использование запросов с ключевым словом РАЗРЕШЕННЫЕ. Это самый правильный и рекомендуемый путь (best practice). Запросы позволяют гибко работать с данными, не вызывая исключительных ситуаций. Вместо объектной выборки лучше написать небольшой запрос к таблице регистра.
  2. Привилегированный режим. Если нам необходимо получить данные для служебных целей (например, для проверки уникальности или расчета итогов), и при этом мы точно знаем, что данные не будут напрямую показаны пользователю, мы можем использовать конструкцию:
    
    УстановитьПривилегированныйРежим(Истина);
    Выборка = РегистрыСведений.ЖурналОтчетовСтатусы.Выбрать(Отбор);
    УстановитьПривилегированныйРежим(Ложь);
    
    В этом режиме проверки RLS полностью игнорируются.

Влияние RLS на уровне полей

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

Резюме для практической работы

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

Соблюдение этих правил позволит вам создавать стабильные и надежные системы на платформе 1С:Предприятие 8.3, которые не будут «падать» при первом же внедрении политик безопасности.

← На главную