В процессе разработки сложных корпоративных систем на платформе 1С:Предприятие часто возникает задача: программно определить, имеет ли определенный пользователь право на чтение конкретного документа или элемента справочника. Ситуация осложняется тем, что стандартные методы платформы часто ограничиваются проверкой только на уровне метаданных, игнорируя ограничения на уровне записей (RLS — Record Level Security). Разберем по шагам, какие инструменты у нас есть и как обойти существующие ограничения платформы.
Первое, что приходит на ум любому разработчику, — это использование встроенной функции ПравоДоступа(). Давайте проанализируем синтаксис этого метода:
ПравоДоступа(<Право>, <ОбъектМетаданных>, <Пользователь/Роль>, <КонтекстПроверки>)
На первый взгляд, наличие третьего параметра <Пользователь/Роль> решает нашу задачу. Однако здесь кроется главная проблема: этот метод проверяет права только на уровне метаданных. Рассмотрим, что это означает на практике:
Истина.ПравоДоступа() все равно вернет Истина, даже если доступ к конкретной ссылке закрыт.Таким образом, для проверки прав "на ссылку" с учетом RLS этот метод не подходит. Выясним, какие альтернативы предлагает Библиотека стандартных подсистем (БСП).
В современных версиях БСП (начиная с 2.4 и выше) реализован производительный механизм управления доступом, основанный на расчете так называемых "ключей доступа". Вместо того чтобы вычислять сложные условия RLS при каждом обращении, система заранее подготавливает данные в специальных регистрах. Проанализируем, как мы можем это использовать для решения нашей задачи.
Основная информация о правах доступа хранится в регистрах сведений: КлючиДоступаПользователей и КлючиДоступаКОбъектам. Чтобы проверить права другого пользователя, нам не обязательно переключаться в его сеанс. Достаточно выполнить запрос к этим регистрам.
Рассмотрим алгоритм проверки:
Пользователи или ВнешниеПользователи).КлючиДоступаКОбъектам ключ, соответствующий нашей ссылке на документ или справочник.КлючиДоступаПользователей для найденного ключа и нашего "целевого" пользователя.Этот способ является наиболее корректным и быстрым в конфигурациях, построенных на БСП, так как он не требует запуска дополнительных сеансов и учитывает актуальные настройки прав доступа. Для поддержания актуальности данных в регистрах можно использовать инструмент для точечного пересчета прав доступа пользователя.
Если нам нужно проверить права "здесь и сейчас", а механизмы ключей доступа в конфигурации не используются или не обновлены, мы можем прибегнуть к методу эмуляции RLS. Посмотрим на логику работы RLS: это фактически добавление дополнительного условия ГДЕ к каждому запросу. Чтобы проверить права другого пользователя, мы можем программно повторить эту логику.
Разберем пример реализации через запрос:
Функция ПроверитьДоступПользователяКОбъекту(ЦелевойПользователь, СсылкаНаОбъект) Экспорт
// Получаем настройки доступа целевого пользователя (например, список разрешенных организаций)
// В типовых конфигурациях это можно сделать через функции модуля УправлениеДоступом
ПараметрыДоступа = УправлениеДоступом.ПараметрыОграниченияДоступа(ЦелевойПользователь, СсылкаНаОбъект.Метаданные().ПолноеИмя());
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Т.Ссылка КАК Ссылка
|ИЗ
| " + СсылкаНаОбъект.Метаданные().ПолноеИмя() + " КАК Т
|ГДЕ
| Т.Ссылка = &СсылкаНаОбъект
| И (" + ПараметрыДоступа.ТекстУсловия + ")";
Запрос.УстановитьПараметр("СсылкаНаОбъект", СсылкаНаОбъект);
// Установка параметров из ПараметрыДоступа...
Возврат НЕ Запрос.Выполнить().Пустой();
КонецФункции
Важный нюанс: для выполнения такого запроса текущий пользователь должен иметь права "Изоляция данных" или обладать полными правами, чтобы иметь возможность прочитать объект в обход собственного RLS и проверить условие для другого пользователя.
В обсуждениях часто упоминается способ с созданием COM-соединения под учетными данными целевого пользователя. Рассмотрим этот вариант. Мы можем инициировать подключение, передав логин и пароль пользователя, и внутри соединения вызвать простую проверку:
Результат = Объект.ПолучитьСсылку().ПолучитьОбъект() <> Неопределено;
Однако проанализируем недостатки этого подхода:
Вместо COM-соединения в современных системах лучше использовать фоновые задания. Хотя запуск фонового задания обычно происходит от имени текущего пользователя, платформа позволяет программно настроить параметры сеанса для выполнения конкретных проверок, если это предусмотрено архитектурой конфигурации.
В составе БСП есть программный интерфейс, который позволяет упростить жизнь разработчику. Рассмотрим модуль УправлениеДоступом. Хотя большинство его функций ориентировано на текущего пользователя, существуют внутренние методы, позволяющие анализировать группы доступа.
Например, мы можем использовать функцию, которая возвращает таблицу разрешенных значений для пользователя:
ТаблицаДоступа = УправлениеДоступом.ТаблицаЗначенийДоступа(Пользователь, ОбъектМетаданных);
Проанализировав эту таблицу (в которой могут быть указаны разрешенные организации, склады или подразделения), мы можем вручную сопоставить реквизиты проверяемого документа с этими данными. Это не является "честной" проверкой платформенного RLS, но на 95% повторяет логику типовых решений. Для комплексного анализа ролей, профилей и ограничений RLS можно использовать обработку для анализа прав и ограничений доступа.
Выясним, какой метод выбрать в зависимости от ситуации:
ПравоДоступа() с указанием пользователя, но помните о необходимости административных прав.Помните, что проверка прав "чужого" пользователя — это всегда работа с данными о безопасности, поэтому такие операции должны выполняться в привилегированных модулях с четким пониманием того, как система хранит настройки ограничений.