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