Как разрешить пользователю выполнять действия с полными правами только внутри одной обработки в 1С?

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

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

Давайте разберем, как грамотно и безопасно решить эту задачу на примере использования обработки «Универсальный отбор и обработка объектов» и ее функциональности «Произвольный алгоритм».

Проанализируем несколько подходов, от самых прямолинейных и рискованных до архитектурно верных и безопасных.

Решение 1: Прямое включение привилегированного режима (Быстро, но очень опасно)

Платформа 1С предоставляет механизм временного отключения проверки прав — привилегированный режим. Код, выполняемый в этом режиме, исполняется на сервере с полными правами, игнорируя любые ограничения текущего пользователя. Включить его можно методом УстановитьПривилегированныйРежим(Истина).

В контексте поля «Произвольный алгоритм» пользователь может написать следующий код:


// Включаем режим, где все можно
УстановитьПривилегированныйРежим(Истина);

// Выполняем действия, требующие полных прав.
// Например, изменяем дату объекта и проводим его.
Объект = ТекущийОбъект.ПолучитьОбъект();
Объект.Дата = '20230115';
Объект.Записать(РежимЗаписиДокумента.Проведение);

// ОБЯЗАТЕЛЬНО выключаем привилегированный режим
УстановитьПривилегированныйРежим(Ложь);

В чем заключается критическая уязвимость этого подхода?

Предоставляя пользователю возможность использовать УстановитьПривилегированныйРежим() в поле для произвольного кода, вы, по сути, даете ему полные права на всю информационную базу. Он не ограничен только изменением даты. Внутри этого блока он может написать любой код: удалить все документы, изменить константы, добавить себе административные роли или даже выполнить код, который наносит вред данным. Вы никак не контролируете, что именно будет выполнено в этом блоке.

Важный технический момент: количество вызовов УстановитьПривилегированныйРежим(Ложь) должно строго соответствовать количеству вызовов УстановитьПривилегированныйРежим(Истина). Нарушение этого баланса приведет к возникновению исключительной ситуации.

Этот метод можно рассматривать только как временное решение при отладке, но никогда — как постоянное решение для работы пользователей.

Решение 2: Программное назначение прав (Категорически не рекомендуется)

Встречается и такой, еще более опасный подход — программное добавление пользователю административной роли прямо в коде. Выглядеть это может так:


// ЭТОТ КОД ЯВЛЯЕТСЯ КРАЙНЕ ОПАСНЫМ ПРИМЕРОМ!
ПользовательИБ = ИнформационнаяБаза.НайтиПоИмени(ИмяПользователя());
Если ПользовательИБ <> Неопределено Тогда
    ПользовательИБОбъект = ПользовательИБ.ПолучитьОбъект();
    НужнаяРоль = Метаданные.Роли.ПолныеПрава;
    ПользовательИБОбъект.Роли.Добавить(НужнаяРоль);
    ПользовательИБОбъект.Записать();
КонецЕсли;

// ... здесь код, требующий прав ...

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

Решение 3: Использование привилегированных общих модулей (Правильный и безопасный подход)

Это рекомендованный и единственно верный способ решения нашей задачи. Суть его в том, чтобы инкапсулировать (спрятать) весь опасный код, требующий полных прав, в специальный серверный общий модуль.

Разберем по шагам, как это реализовать:

  1. Создание привилегированного общего модуля.

    В конфигураторе создайте новый общий модуль, например, с именем РаботаСДокументамиПривилегированный. В его свойствах необходимо установить следующие флаги:

    • Сервер — код будет выполняться на стороне сервера.
    • Вызов сервера — к модулю можно будет обратиться с клиента.
    • Привилегированный — это ключевой флаг. Он указывает платформе, что все процедуры и функции этого модуля должны выполняться с полными правами, вне зависимости от прав текущего пользователя.
  2. Разработка экспортной процедуры.

    Внутри созданного модуля напишем экспортную процедуру, которая будет выполнять нашу задачу — изменение даты документа. Важно, что именно здесь, под полным контролем разработчика, мы можем и должны реализовать все необходимые проверки.

    
    // Содержимое общего модуля "РаботаСДокументамиПривилегированный"
    
    Процедура ИзменитьДатуДокумента(СсылкаНаДокумент, НоваяДата) Экспорт
    
        // Шаг 1. Проверяем входные параметры и бизнес-логику.
        // Это наш "фильтр безопасности". Пользователь не сможет обойти эти проверки.
        Если ТипЗнч(СсылкаНаДокумент) <> Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
            ВызватьИсключение "Изменять дату можно только у документов реализации!";
        КонецЕсли;
    
        Если НоваяДата > ТекущаяДата() Тогда
            ВызватьИсключение "Нельзя устанавливать будущую дату!";
        КонецЕсли;
        
        // Шаг 2. Выполняем действие, требующее прав.
        ОбъектДокумента = СсылкаНаДокумент.ПолучитьОбъект();
        ОбъектДокумента.Дата = НоваяДата;
        
        // Используем конструкцию Попытка-Исключение для корректной обработки ошибок записи
        Попытка
            ОбъектДокумента.Записать(РежимЗаписиДокумента.Проведение);
        Исключение
            // Передаем текст ошибки на уровень пользователя
            ВызватьИсключение ОписаниеОшибки();
        КонецПопытки;
    
    КонецПроцедуры
    
  3. Вызов процедуры из обработки.

    Теперь в поле «Произвольный алгоритм» пользователь пишет не опасный код, а всего лишь одну строку — вызов нашей безопасной процедуры.

    
    // Код в поле "Произвольный алгоритм"
    НоваяДатаДляДокумента = Дата(2023, 10, 20);
    РаботаСДокументамиПривилегированный.ИзменитьДатуДокумента(ТекущийОбъект, НоваяДатаДляДокумента);
    

Преимущества этого подхода очевидны:

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

← На главную