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