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