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