В процессе разработки на платформе 1С часто возникает вопрос о взаимодействии запросов и механизма ограничения прав доступа на уровне записей (RLS). Рассмотрим типичную ситуацию: у пользователя есть ограничения на просмотр данных по определенным организациям, но в запросе поле Организация не выводится в результат. Что произойдет в этом случае — платформа выдаст ошибку или выполнит запрос, проигнорировав ограничения? Разберемся в этом вопросе подробно.
Проанализируем исходную задачу. Есть регистр сведений, в котором одно из измерений — Организация. У пользователя, под которым выполняется код, настроены права RLS, ограничивающие доступ к записям по этому полю. Мы хотим выполнить запрос, который считает количество уникальных значений другого измерения, при этом поле Организация в секции ВЫБРАТЬ отсутствует.
ВЫБРАТЬ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Рег1.Измерения1) КАК Сч
ИЗ
РегистрСведений.Рег1 КАК Рег1
Вопрос в том, каково будет поведение системы. Интуитивно может показаться, что раз мы не запрашиваем поле Организация, то и проверять права на него не нужно. Но это не так.
Ключевой момент, который нужно понять: механизм RLS работает на уровне записей (строк) таблицы базы данных, а не на уровне полей итоговой выборки запроса.
Когда платформа 1С выполняет запрос к таблице, для которой у текущего пользователя есть ограничения, она не просто выполняет ваш исходный запрос. Перед отправкой в СУБД платформа модифицирует его, добавляя в него дополнительные условия (аналогичные секции WHERE в SQL), которые как раз и реализуют настроенные ограничения.
В нашем примере, даже если поле Организация не указано в ВЫБРАТЬ, запрос все равно обращается к физической таблице РегистрСведений.Рег1. Платформа начинает последовательно "читать" записи этой таблицы для выполнения агрегатной функции КОЛИЧЕСТВО. Как только она наталкивается на запись, значение поля Организация в которой не соответствует правам пользователя, происходит нарушение доступа. Стандартное поведение платформы в такой ситуации — прервать выполнение и сгенерировать ошибку «У пользователя недостаточно прав на исполнение операции над базой данных».
Таким образом, мы получаем однозначный ответ на исходный вопрос: платформа выдаст ошибку. Это не баг, а корректное и документированное поведение, обеспечивающее целостность системы прав доступа. Нельзя получить агрегированные данные по всему регистру, если у вас есть доступ только к его части, так как это само по себе является утечкой информации (например, можно косвенно узнать общие обороты компании, даже не видя конкретных документов).
Самый правильный и стандартный способ решения этой задачи — использовать ключевое слово РАЗРЕШЕННЫЕ в запросе. Это специальная инструкция для платформы, которая меняет ее поведение при работе с RLS.
Посмотрим, как изменится наш запрос:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Рег1.Измерения1) КАК Сч
ИЗ
РегистрСведений.Рег1 КАК Рег1
Что делает слово РАЗРЕШЕННЫЕ? Оно говорит платформе: «При выполнении этого запроса, если встретишь запись, к которой у пользователя нет доступа, не генерируй ошибку, а просто пропусти ее, как будто ее не существует».
В результате запрос будет выполнен успешно, а агрегатная функция КОЛИЧЕСТВО посчитает уникальные значения только по тем записям, организации в которых доступны текущему пользователю. Ошибки не возникнет.
Важный момент: Используя РАЗРЕШЕННЫЕ, всегда помните, что вы получаете данные не по всей таблице, а только по разрешенной пользователю части. Если вы формируете отчет об общих итогах, эти итоги будут неполными, но пользователь не получит никакого сообщения об ошибке. Это может ввести в заблуждение, если он не осведомлен о своих ограничениях.
В некоторых серверных сценариях может потребоваться получить данные без учета каких-либо ограничений. Например, для выполнения служебных расчетов, результаты которых не показываются пользователю напрямую, или для проверки целостности данных.
Для таких случаев существует серверный метод УстановитьПривилегированныйРежим().
Как это работает:
УстановитьПривилегированныйРежим(Истина) полностью отключает проверку прав для всего последующего кода в рамках текущего серверного вызова.РАЗРЕШЕННЫЕ).УстановитьПривилегированныйРежим(Ложь).Пример использования:
&НаСервере
Процедура РассчитатьКоличествоНаСервере()
УстановитьПривилегированныйРежим(Истина);
Попытка
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Рег1.Измерения1) КАК Сч
|ИЗ
| РегистрСведений.Рег1 КАК Рег1";
Результат = Запрос.Выполнить().Выгрузить();
Если Результат.Количество() > 0 Тогда
Сообщить("Общее количество: " + Результат[0].Сч);
КонецЕсли;
Исключение
// Обработка возможных ошибок
КонецПопытки;
УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры
Внимание! Привилегированный режим — это очень мощный и потенциально опасный инструмент. Используйте его с большой осторожностью и только тогда, когда это действительно необходимо. Неправильное использование может привести к серьезным нарушениям безопасности, позволив пользователю получить доступ к данным, которые ему видеть не положено.
Подведем итог анализа работы RLS в запросах:
ВЫБРАТЬ РАЗРЕШЕННЫЕ. Запрос вернет данные только по доступным записям.УстановитьПривилегированныйРежим(), но делайте это осознанно и с осторожностью.Понимание этих принципов позволяет писать надежный и безопасный код, который корректно работает в системе с настроенными правами доступа.