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