При разработке и администрировании систем на платформе 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда код, отлично работающий под учетной записью с полными правами, отказывается выполнять свои функции у рядовых пользователей. Типичным примером является работа со списком пользователей информационной базы с использованием метода ПользователиИнформационнойБазы.ПолучитьПользователей(). Если у текущего пользователя в конфигураторе не установлена роль с правом "Администрирование" (в самом корне метаданных конфигурации), платформа мгновенно блокирует выполнение кода и вызывает исключение нарушения прав доступа.
В этой статье мы подробно разберем, как определить, какие именно права требуются для совершения того или иного действия в системе, почему стандартный призыв "использовать привилегированный режим" на сервере срабатывает далеко не всегда, и как правильно решать подобные задачи в современных конфигурациях в соответствии со стандартами разработки фирмы 1С.
Рассмотрим классическую ситуацию. Разработчик пишет код, предназначенный для получения списка зарегистрированных в системе пользователей:
ВыборкаПользователей = ПользователиИнформационнойБазы.ПолучитьПользователей();
Для Каждого ТекущийПользователь Из ВыборкаПользователей Цикл
// Обработка данных пользователя
КонецЦикла;
При запуске этого фрагмента от имени обычного пользователя система возвращает ошибку нарушения прав доступа. Если мы обратимся к Синтакс-Помощнику 1С для метода ПолучитьПользователей(), то в разделе "Примечание" мы увидим жесткое платформенное ограничение: "Данный метод доступен пользователям, имеющим административные права."
Это означает, что на уровне самой технологической платформы 1С наложен запрет на чтение таблицы пользователей ИБ без наличия административной роли. Прямой обход этого ограничения "в лоб" под обычным пользователем невозможен. Но как быть, если нам действительно нужно вывести список пользователей в какой-либо отчет или форму, но наделять обычного сотрудника правами администратора категорически запрещено правилами безопасности?
Первой идеей, которая возникает у большинства разработчиков, является временное повышение привилегий исполняемого кода. На форумах часто советуют просто вставить вызов специального метода платформы:
УстановитьПривилегированныйРежим(Истина);
СписокПользователей = ПользователиИнформационнойБазы.ПолучитьПользователей();
УстановитьПривилегированныйРежим(Ложь);
Однако при выполнении этого кода на сервере под ограниченным пользователем разработчик снова получает отказ в доступе. Выясним глубокие технологические причины, почему привилегированный режим в данном случае "бездействует":
УстановитьПривилегированныйРежим(Истина). Платформа молча или с ошибкой игнорирует попытку повысить привилегии, чтобы вредоносный код не мог обойти ограничения безопасности. Для исправления этой ситуации внешнюю обработку необходимо запускать с явным отключением безопасного режима (например, через механизмы БСП с предоставлением соответствующих разрешений в безопасном профиле).УстановитьПривилегированныйРежим() эффективно работает только в серверном контексте, но его вызов "напрямую" в модуле формы (даже на сервере) или в обычном общем модуле без специальных свойств не всегда приводит к желаемому результату. Для гарантированного и безопасного выполнения кода в обход прав текущего пользователя необходимо выносить тяжелые платформенные операции в специализированный общий модуль.Для того чтобы привилегированный режим сработал корректно, нам нужно выполнить следующие шаги:
РаботаСПользователямиСерверПривилегированный).
// Функция в привилегированном общем модуле
Функция ПолучитьСписокИменПользователейИБ() Экспорт
СписокИмен = Новый Массив;
Выборка = ПользователиИнформационнойБазы.ПолучитьПользователей();
Для Каждого ПользовательИБ Из Выборка Цикл
СписокИмен.Добавить(ПользовательИБ.Имя);
КонецЦикла;
Возврат СписокИмен;
КонецФункции
Методические материалы на ИТС подробно описывают разницу в проверке прав при чтении и создании пользователей ИБ без прав администрирования. Проанализируем эти нюансы подробнее:
ПользователиИнформационнойБазы.СоздатьПользователя(). Он также может заполнить все ключевые свойства объекта (имя, пароль, роли). Однако при попытке вызвать метод Записать() платформа заблокирует транзакцию. Записать созданного пользователя можно только передав этот объект на сервер в привилегированный общий модуль, где метод Записать() выполнится в привилегированном режиме.ПолучитьПользователей() жестко требует административных прав в текущем сеансе при интерактивном вызове, либо его исполнение должно происходить строго внутри серверного кода привилегированного модуля. На клиенте этот метод вызвать под ограниченными правами невозможно ни при каких обстоятельствах.В современных конфигурациях 1С (таких как ERP, УТ, КА, БП, ЗУП), где активно используется БСП (Библиотека стандартных подсистем), прямое обращение к методам менеджера ПользователиИнформационнойБазы напрямую считается устаревшим и не рекомендуется стандартами разработки. Это связано с тем, что БСП предоставляет гораздо более удобную и безопасную абстракцию.
В БСП реализовано разделение на пользователей информационной базы (уровень платформы) и элементы справочников:
Справочник.Пользователи — для реальных сотрудников и пользователей системы.Справочник.ВнешниеПользователи — для представителей контрагентов, клиентов, партнеров.При создании и изменении пользователей БСП автоматически синхронизирует элементы справочников с пользователями ИБ, записывая уникальный идентификатор пользователя ИБ (UUID) в реквизит справочника ИдентификаторПользователяИБ. Чтение элементов справочника Пользователи доступно обычным пользователям в соответствии со стандартными ролями чтения. Таким образом, для получения списка работающих в базе людей вам совершенно не нужно вызывать методы ПользователиИнформационнойБазы! Достаточно написать стандартный запрос к справочнику:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Пользователи.Наименование КАК ПолноеИмя,
| Пользователи.ИдентификаторПользователяИБ КАК Идентификатор
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| НЕ Пользователи.Недействителен";
РезультатЗапроса = Запрос.Выполнить();
Такой подход полностью решает проблему прав доступа: пользователю достаточно иметь базовые права на чтение справочника пользователей, при этом конфиденциальные системные настройки платформы остаются в безопасности.
Ранее для решения этой задачи разработчикам приходилось включать технологический журнал, анализировать логи СУБД или запускать отладку под специально созданным пользователем с урезанными правами, пытаясь методом проб и ошибок нащупать недостающую роль. Но сегодня фирма "1С" предоставляет встроенный революционный инструмент.
Начиная с версии платформы 8.5.5 (и в современных релизах ветки 8.3.25+), добавлен мощнейший механизм под названием "Анализ использования прав доступа". Разберем по шагам, как им пользоваться для поиска недостающих прав:
Этот инструмент избавляет разработчиков от долгого чтения кода и позволяет мгновенно точечно настроить профили безопасности и роли для пользователей, минимизируя риски предоставления лишних прав (таких как полные права администратора).