Почему не проводится документ из внешней обработки и как обойти безопасный режим в 1С?

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

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


Ошибка при вызове метода контекста (Записать)
    ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
по причине:
Не удалось провести: "Поступление наличных"!

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

Анализ ошибки и выяснение причин сбоя

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


{ОбщийМодуль.ОбменДаннымиСобытия.Модуль(1233)}: Ошибка выполнения правил регистрации объектов для плана обмена ОбменЗарплата3Бухгалтерия3.
Описание ошибки:
{ОбщийМодуль.ОбменДаннымиВызовСервера.Модуль(644)}: Ошибка при получении значения атрибута контекста (ПравилаРегистрацииОбъектов)
    Возврат ПараметрыСеанса.ПравилаРегистрацииОбъектов;
по причине:
Нарушение прав доступа!

Рассмотрим, какая цепочка событий приводит к нарушению прав доступа:

  1. При проведении документа платформа и механизмы Библиотеки Стандартных Подсистем (БСП) вызывают подписки на события для регистрации изменений на узлах планов обмена (например, синхронизация между конфигурациями «Бухгалтерия предприятия» и «Зарплата и управление персоналом»).
  2. Для определения необходимости регистрации выполняется чтение правил, которые кэшируются в объекте ПараметрыСеанса.ПравилаРегистрацииОбъектов.
  3. У обычных пользователей в типовых конфигурациях нет прямых прав на чтение этих параметров сеанса — данный программный код рассчитан на исполнение строго в привилегированном режиме.
  4. Попытка разработчика принудительно вызвать УстановитьПривилегированныйРежим(Истина) в модуле внешней обработки не дает результата: функция ПривилегированныйРежим() продолжает возвращать Ложь.

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

Почему обработка выполняется в безопасном режиме?

Выясним, почему безопасный режим остается активным, даже если в функции СведенияОВнешнейОбработке() указана строка ПараметрыРегистрации.БезопасныйРежим = Ложь;:

  1. Интерактивное открытие через «Файл — Открыть»: если пользователь без административных прав открывает внешний файл через меню «Файл — Открыть», платформа всегда принудительно включает безопасный режим ради безопасности системы, независимо от содержимого файла.
  2. Кэширование настроек в базе данных: если обработка подключена через справочник «Дополнительные отчеты и обработки», признак безопасного режима сохраняется в реквизите элемента справочника. Простого исправления исходного кода обработки недостаточно: администратор должен зайти в справочник и обновить обработку из файла, согласившись с изменением параметров безопасности.
  3. Механизм контроля разрешений БСП: в актуальных версиях БСП снятия одного лишь флага безопасного режима недостаточно, требуется явный запрос разрешений на доступ к привилегированному режиму.

Способ 1. Запрос разрешения на привилегированный режим через БСП

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

Рассмотрим фрагмент кода регистрации:


Функция СведенияОВнешнейОбработке() Экспорт

    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
    ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
    ПараметрыРегистрации.Версия = "1.0";
    ПараметрыРегистрации.БезопасныйРежим = Ложь;

    // Запрашиваем разрешение на использование привилегированного режима
    Разрешение = РаботаВБезопасномРежиме.РазрешениеНаИспользованиеПривилегированногоРежима(
        НСтр("ru = 'Для проведения документов и регистрации изменений в планах обмена'")
    );
    ПараметрыРегистрации.Разрешения.Добавить(Разрешение);

    // Добавление команд обработки
    НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
    НоваяКоманда.Представление = НСтр("ru = 'Загрузка документов из XML'");
    НоваяКоманда.Идентификатор = "ЗагрузитьДокументы";
    НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
    НоваяКоманда.ПоказыватьОповещение = Истина;

    Возврат ПараметрыРегистрации;

КонецФункции

После внесения изменений выполним следующие шаги:

  1. Зайдем в информационную базу под учетной записью с правами администратора.
  2. Откроем раздел «Администрирование» — «Печатные формы, отчеты и обработки» — «Дополнительные отчеты и обработки».
  3. Обновим обработку из измененного файла. Программа покажет окно предупреждения безопасности и запросит подтверждение на предоставление разрешений.
  4. Согласимся с применением разрешений. Теперь обработка сможет корректно запускать УстановитьПривилегированныйРежим(Истина) при вызове команд через интерфейс конфигурации.

Способ 2. Программное создание объекта обработки без безопасного режима

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


ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ПолноеИмяФайла, Ложь);
ВнешняяОбработкаОбъект.ОбработатьДанные(ДокументОбъект);

Передавая Ложь вторым параметром, мы отключаем безопасный режим для создаваемого экземпляра обработки, что позволит коду внутри нее повышать привилегии при записи объектов.

Способ 3. Перенос функционала в расширение конфигурации

Если регламент предприятия исключает работу с дополнительными обработками или требуется регулярное интерактивное открытие файла пользователями без админ-прав, перенесем логику в расширение конфигурации (файл с расширением .cfe):

  1. Создадим новое расширение конфигурации в конфигураторе.
  2. Перенесем форму и программный модуль обработки в расширение.
  3. Подключим расширение к рабочей информационной базе.
  4. В списке расширений в режиме «1С:Предприятие» снимем флажок «Безопасный режим».

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

Способ 4. Вынесение записи документа в привилегированный общий модуль

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

  1. В дереве метаданных добавим или выберем серверный общий модуль, у которого установлено свойство Привилегированный.
  2. Создадим в нем экспортную процедуру для записи документа:

Процедура ЗаписатьДокументВПривилегированномРежиме(ДокументОбъект) Экспорт
    ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры
  1. Во внешней обработке вместо прямого вызова метода ДокументОбъект.Записать(...) вызываем созданную процедуру привилегированного общего модуля. Так как модуль является привилегированным изначально, обращение к ПараметрыСеанса.ПравилаРегистрацииОбъектов пройдет без ошибки прав доступа даже при вызове из безопасного контекста.
← На главную