Как работают запросы с ограничением прав доступа (RLS), если поле с ограничением не выбирается?

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

В процессе разработки на платформе 1С часто возникает вопрос о взаимодействии запросов и механизма ограничения прав доступа на уровне записей (RLS). Рассмотрим типичную ситуацию: у пользователя есть ограничения на просмотр данных по определенным организациям, но в запросе поле Организация не выводится в результат. Что произойдет в этом случае — платформа выдаст ошибку или выполнит запрос, проигнорировав ограничения? Разберемся в этом вопросе подробно.

Проанализируем исходную задачу. Есть регистр сведений, в котором одно из измерений — Организация. У пользователя, под которым выполняется код, настроены права RLS, ограничивающие доступ к записям по этому полю. Мы хотим выполнить запрос, который считает количество уникальных значений другого измерения, при этом поле Организация в секции ВЫБРАТЬ отсутствует.


ВЫБРАТЬ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Рег1.Измерения1) КАК Сч
ИЗ
    РегистрСведений.Рег1 КАК Рег1

Вопрос в том, каково будет поведение системы. Интуитивно может показаться, что раз мы не запрашиваем поле Организация, то и проверять права на него не нужно. Но это не так.

Принцип работы RLS: ограничение на уровне записей

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

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

В нашем примере, даже если поле Организация не указано в ВЫБРАТЬ, запрос все равно обращается к физической таблице РегистрСведений.Рег1. Платформа начинает последовательно "читать" записи этой таблицы для выполнения агрегатной функции КОЛИЧЕСТВО. Как только она наталкивается на запись, значение поля Организация в которой не соответствует правам пользователя, происходит нарушение доступа. Стандартное поведение платформы в такой ситуации — прервать выполнение и сгенерировать ошибку «У пользователя недостаточно прав на исполнение операции над базой данных».

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

Решение 1: Ключевое слово РАЗРЕШЕННЫЕ

Самый правильный и стандартный способ решения этой задачи — использовать ключевое слово РАЗРЕШЕННЫЕ в запросе. Это специальная инструкция для платформы, которая меняет ее поведение при работе с RLS.

Посмотрим, как изменится наш запрос:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Рег1.Измерения1) КАК Сч
ИЗ
    РегистрСведений.Рег1 КАК Рег1

Что делает слово РАЗРЕШЕННЫЕ? Оно говорит платформе: «При выполнении этого запроса, если встретишь запись, к которой у пользователя нет доступа, не генерируй ошибку, а просто пропусти ее, как будто ее не существует».

В результате запрос будет выполнен успешно, а агрегатная функция КОЛИЧЕСТВО посчитает уникальные значения только по тем записям, организации в которых доступны текущему пользователю. Ошибки не возникнет.

Важный момент: Используя РАЗРЕШЕННЫЕ, всегда помните, что вы получаете данные не по всей таблице, а только по разрешенной пользователю части. Если вы формируете отчет об общих итогах, эти итоги будут неполными, но пользователь не получит никакого сообщения об ошибке. Это может ввести в заблуждение, если он не осведомлен о своих ограничениях.

Решение 2: Привилегированный режим

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

Для таких случаев существует серверный метод УстановитьПривилегированныйРежим().

Как это работает:

  1. Вызов УстановитьПривилегированныйРежим(Истина) полностью отключает проверку прав для всего последующего кода в рамках текущего серверного вызова.
  2. Затем выполняется код, которому нужен полный доступ к данным (например, наш запрос без слова РАЗРЕШЕННЫЕ).
  3. После выполнения кода крайне рекомендуется вернуть проверку прав вызовом УстановитьПривилегированныйРежим(Ложь).

Пример использования:


&НаСервере
Процедура РассчитатьКоличествоНаСервере()
    
    УстановитьПривилегированныйРежим(Истина);
    
    Попытка
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Рег1.Измерения1) КАК Сч
            |ИЗ
            |    РегистрСведений.Рег1 КАК Рег1";
            
        Результат = Запрос.Выполнить().Выгрузить();
        Если Результат.Количество() > 0 Тогда
            Сообщить("Общее количество: " + Результат[0].Сч);
        КонецЕсли;
    Исключение
        // Обработка возможных ошибок
    КонецПопытки;
    
    УстановитьПривилегированныйРежим(Ложь);
    
КонецПроцедуры

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

Выводы

Подведем итог анализа работы RLS в запросах:

  1. RLS применяется к записи целиком. Если у пользователя нет прав хотя бы на одно поле записи, он не имеет доступа ко всей записи.
  2. Запрос к таблице с ограниченными записями вызовет ошибку прав доступа, даже если запрещенные поля не выбираются в результат.
  3. Для корректного выполнения запросов с учетом прав используйте ключевое слово ВЫБРАТЬ РАЗРЕШЕННЫЕ. Запрос вернет данные только по доступным записям.
  4. Для полного отключения проверки прав в серверном коде используйте УстановитьПривилегированныйРежим(), но делайте это осознанно и с осторожностью.

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

← На главную