Что возвращает метод РегистрСведений.ИмяРегистра.Выбрать() при отсутствии прав доступа и как правильно обрабатывать такие ситуации в 1С?

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

При разработке конфигураций на платформе «1С:Предприятие 8» одной из важнейших задач является обеспечение безопасности и корректного разграничения прав доступа. Довольно часто разработчики сталкиваются с ситуацией, когда программный код обращается к объектам метаданных (например, регистрам сведений, справочникам или документам), на чтение которых у текущего пользователя нет прав. В этой статье мы подробно разберем, как ведет себя платформа при вызове метода Выбрать(), в чем заключается коварство ключевого слова РАЗРЕШЕННЫЕ в запросах, и как правильно реализовать проверку прав, чтобы избежать аварийного завершения работы программы.

Что происходит при вызове метода Выбрать() без прав доступа?

Если у пользователя в его ролях полностью отсутствует право «Чтение» на определенный регистр сведений, то при попытке вызвать метод РегистрСведений.ИмяРегистра.Выбрать() платформа «1С:Предприятие 8» всегда генерирует исключение (ошибку выполнения) «Нарушение прав доступа».

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

Мифы и реальность работы ключевого слова РАЗРЕШЕННЫЕ

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

Ключевое слово РАЗРЕШЕННЫЕ работает исключительно на уровне ограничений доступа к записям (RLS — Row-Level Security). Это означает следующее:

  1. Базовое право есть, но действует RLS: Если у пользователя есть роль, дающая право «Чтение» на регистр сведений в целом, но настроены правила RLS (например, разрешено видеть данные только по определенной организации), запрос без слова РАЗРЕШЕННЫЕ вызовет ошибку доступа при первой же попытке прочесть «чужую» строку. Если же в запросе указано слово РАЗРЕШЕННЫЕ, платформа молча отфильтрует недоступные строки и вернет пустой или частично заполненный результат без генерации ошибок.
  2. Базового права нет вообще: Если у пользователя нет ни одной роли, позволяющей читать данный регистр сведений на уровне метаданных, то платформа прервет выполнение любого запроса (даже содержащего ключевое слово РАЗРЕШЕННЫЕ) еще на этапе компиляции схемы запроса. Система сразу выбросит исключение «Нарушение прав доступа».

Как правильно проверять права доступа в коде?

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

Для этого в платформе существует встроенный метод ПравоДоступа(). Рассмотрим стандартный шаблон проверки:


Если ПравоДоступа("Чтение", Метаданные.РегистрыСведений.ИмяВашегоРегистра) Тогда
    // Безопасное чтение данных
    Выборка = РегистрыСведений.ИмяВашегоРегистра.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Обработка данных
    КонецЦикла;
Иначе
    // Альтернативная логика или уведомление пользователя
    ВызватьИсключение "У вас недостаточно прав для выполнения этой операции.";
КонецЕсли;

Коварство метода ПравоДоступа() в привилегированном режиме

Существует критически важная деталь, о которой часто забывают даже опытные разработчики. Если вышеуказанный код выполняется на стороне сервера в привилегированном режиме (например, внутри привилегированного общего модуля или после явного вызова УстановитьПривилегированныйРежим(Истина)), метод ПравоДоступа() с двумя параметрами всегда вернет Истина.

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

Чтобы узнать реальные права текущего пользователя, находясь в привилегированном контексте, необходимо обязательно передавать третьим параметром конкретного пользователя информационной базы:


ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
ЕстьДоступ = ПравоДоступа("Чтение", Метаданные.РегистрыСведений.ИмяВашегоРегистра, ТекущийПользовательИБ);

Если ЕстьДоступ Тогда
    // Чтение разрешено реальному пользователю
КонецЕсли;

Стандарты разработки 1С: проверка прав против проверки ролей

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

Проверять возможность работы с конкретной таблицей всегда нужно через права доступа к объекту метаданных: ПравоДоступа("Чтение", Метаданные.РегистрыСведений.ИмяРегистра). Метод РольДоступна() допускается использовать только для проверки общих административных или сугубо логических прав интерфейса, не связанных напрямую со структурой хранения данных.

Использование механизмов БСП (Библиотеки стандартных подсистем)

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

Рассмотрим два полезных метода:

  1. УправлениеДоступом.ЧтениеРазрешено(ОписаниеДанных) — этот метод проверяет доступность объекта (справочника, документа, регистра) как на уровне метаданных, так и с учетом ограничений RLS. Возвращает булево значение.
  2. УправлениеДоступом.ПроверитьЧтениеРазрешено(ОписаниеДанных) — если у пользователя нет прав на чтение, эта процедура сама корректно сгенерирует исключение со стандартным системным текстом ошибки доступа, что избавляет вас от необходимости вручную прописывать генерацию исключений.

Пример использования функций БСП в коде:


// Проверяем возможность чтения регистра сведений через БСП
Если УправлениеДоступом.ЧтениеРазрешено(Метаданные.РегистрыСведений.ИмяВашегоРегистра) Тогда
    // Чтение разрешено, выполняем безопасный запрос
Иначе
    // Обработка ситуации отсутствия прав
КонецЕсли;

Привилегированный режим как архитектурное решение

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

В таких сценариях лучшей практикой проектирования систем на платформе «1С:Предприятие 8» является вынос логики чтения данных в привилегированные общие модули либо программное включение привилегированного режима перед чтением:


УстановитьПривилегированныйРежим(Истина);

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

УстановитьПривилегированныйРежим(Ложь);

Использование этого подхода позволяет безопасно выполнять необходимые расчеты и при этом не открывать пользователям лишние права на чтение конфиденциальных бизнес-данных напрямую из интерфейса программы.

← На главную