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

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

Рано или поздно перед разработчиком 1С встает задача автоматизации обмена или предоставления возможности импорта данных из внешних систем обычным пользователям. Ситуация значительно усложняется, когда загружаемый файл XML содержит объекты (справочники, документы, регистры), на запись которых у текущего пользователя нет и не должно быть прав в системе. Как решить эту дилемму, не превращая систему в «решето» безопасности и не раздавая полные права всем сотрудникам подряд? Давайте разберем эту проблему по шагам и проанализируем наиболее эффективные практические варианты решения.

Суть проблемы и ограничения платформы

Когда мы пытаемся выполнить загрузку через стандартную обработку «Универсальный обмен данными в формате XML» от имени обычного пользователя, система мгновенно натыкается на жесткие ограничения прав доступа. Если у пользователя нет роли ПолныеПрава, мы сталкиваемся со следующими препятствиями:

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

Почему простое использование УстановитьПривилегированныйРежим() на клиенте не работает

Давайте проанализируем популярную ошибку. Часто в кодовой базе пытаются просто вызвать метод УстановитьПривилегированныйРежим(Истина) непосредственно в коде формы обработки перед началом чтения XML. Выясним причину неудачи такого подхода:

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

Таким образом, весь процесс чтения файла, разбора XML и записи объектов должен происходить в серверном контексте. На клиенте мы можем только выбрать файл и передать его (или его адрес во временном хранилище) на сервер.

Способ 1. Использование привилегированного общего модуля (Рекомендуемый)

Рассмотрим наиболее элегантный и архитектурно правильный способ решения задачи. Мы создадим специальный общий модуль, который будет выполнять чтение и запись объектов на сервере без проверки прав текущего пользователя.

Разберем по шагам реализацию этого механизма:

  1. Создадим в конфигураторе новый общий модуль, назовем его, например, ОбменДаннымиПривилегированный.
  2. В свойствах общего модуля установим флажки Сервер и Привилегированный. Флажок «Привилегированный» означает, что любой код внутри этого модуля будет выполняться с полными правами базы данных, игнорируя ограничения ролей текущего пользователя.
  3. Перенесем логику чтения XML-файла и записи объектов в этот модуль.

Посмотрим на пример реализации процедуры в привилегированном общем модуле:


Процедура ВыполнитьЗагрузкуФайлаНаСервере(АдресФайлаВоВременномХранилище) Экспорт
    
    // Получаем файл из временного хранилища на сервере
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xml");
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресФайлаВоВременномХранилище);
    ДвоичныеДанные.Записать(ИмяВременногоФайла);
    
    // Инициализируем чтение XML
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.ОткрытьФайл(ИмяВременногоФайла);
    
    // Используем стандартные механизмы загрузки 1С,
    // запускаемые в привилегированном контексте общего модуля.
    ОбработкаОбмена = Обработки.УниверсальныйОбменДаннымиВФорматеXML.Создать();
    ОбработкаОбмена.РежимОбмена = "Загрузка";
    ОбработкаОбмена.ИмяФайлаОбмена = ИмяВременногоФайла;
    
    // Выполняем загрузку под полными правами модуля
    ОбработкаОбмена.ВыполнитьЗагрузку();
    
    ЧтениеXML.Закрыть();
    Попытка
        УдалитьФайлы(ИмяВременногоФайла);
    Исключение
        ЗаписьЖурналаРегистрации("ОбменДанными", УровеньЖурналаРегистрации.Предупреждение,,, 
            "Не удалось удалить временный файл: " + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
    
КонецПроцедуры

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


&НаКлиенте
Процедура ВыбратьИЗагрузитьФайл(Команда)
    
    ПараметрыВыбора = Новый ПараметрыДиалогаВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    ПараметрыВыбора.Фильтр = "Файлы обмена (*.xml)|*.xml";
    ПараметрыВыбора.МножественныйВыбор = Ложь;
    
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораФайлаДляЗагрузки", ЭтотОбъект);
    НачатьПомещениеФайлаНаСервер(ОписаниеОповещения,,, ПараметрыВыбора, УникальныйИдентификатор);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораФайлаДляЗагрузки(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
    
    Если Результат Тогда
        ВыполнитьЗагрузкуНаСервере(Адрес);
        ПоказатьПредупреждение(, "Загрузка данных успешно завершена!");
    КонецЕсли;
    
КонецПроцедуры

&НаСервере
Процедура ВыполнитьЗагрузкуНаСервере(АдресХранилища)
    // Вызываем процедуру из нашего привилегированного общего модуля
    ОбменДаннымиПривилегированный.ВыполнитьЗагрузкуФайлаНаСервере(АдресХранилища);
КонецПроцедуры

Способ 2. Запуск загрузки через фоновое задание

Если загружаемый файл имеет большой объем, выполнение его в основном сеансе пользователя приведет к зависанию интерфейса программы. Более того, веб-клиент может прервать соединение по таймауту. В этом случае идеальным решением является использование механизма фоновых заданий.

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

Рассмотрим схему реализации:

  1. Пользователь выбирает файл на клиенте, который помещается во временное хранилище.
  2. На сервере запускается фоновое задание, выполняющее процедуру привилегированного модуля.
  3. Пользователю выводится индикатор загрузки (длительная операция), пока фоновое задание отрабатывает в фоне.

Посмотрим на пример кода запуска фонового задания:


&НаСервере
Функция ЗапуститьЗагрузкуВФоне(АдресХранилища)
    
    ПараметрыПроцедуры = Новый Массив;
    ПараметрыПроцедуры.Добавить(АдресХранилища);
    
    // Запускаем фоновое задание в привилегированном режиме
    Задание = ФоновыеЗадания.Выполнить(
        "ОбменДаннымиПривилегированный.ВыполнитьЗагрузкуФайлаНаСервере", 
        ПараметрыПроцедуры, 
        Новый УникальныйИдентификатор, 
        "Загрузка данных из XML под ограниченными правами"
    );
    
    Возврат Задание.УникальныйИдентификатор;
    
КонецФункции

Способ 3. Выделенный сеанс "пользователя обмена"

Если доработка конфигурации нежелательна или ограничена требованиями поддержки вендора, можно использовать организационное решение. Создается специальный служебный пользователь, например, ПользовательЗагрузкиДанных, которому выдается роль ПолныеПрава.

Для минимизации рисков человеческого фактора настраивается автоматический запуск системы под этим пользователем с последующим выходом из нее:

  1. При запуске сеанса под этим пользователем сразу открывается окно выбора файла для загрузки (это настраивается в модуле управляемого приложения в процедуре ПриНачалеРаботыСистемы).
  2. После того как пользователь выбрал файл и загрузка успешно завершилась, сеанс 1С автоматически завершает работу программы командой ЗавершитьРаботуСистемы(Ложь).

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

Критически важный нюанс: изменение ролей «на лету»

В процессе обсуждений на форумах часто возникает идея динамически добавлять пользователю роль с полными правами непосредственно перед загрузкой, а после загрузки — удалять её программными методами через объект ПользовательИнформационнойБазы.

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

Информационная безопасность: «Обезьяна с гранатой»

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

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

Как минимизировать риски при реализации обмена под ограниченными правами:

  1. Проверка схемы данных. Перед передачей файла в процедуру загрузки обязательно проверяйте структуру XML. Разрешайте загрузку только тех типов объектов, которые строго регламентированы правилами обмена.
  2. Контроль каталога обмена. Не давайте пользователю возможность выбирать произвольный файл с его локального диска. Организуйте процесс так, чтобы файлы обмена выгружались автоматически в закрытый сетевой каталог, к которому у обычного пользователя нет доступа на запись. Обработка должна сама забирать файл из этого доверенного источника.
  3. Логирование операций. Всегда записывайте в Журнал регистрации информацию о том, какой пользователь инициировал загрузку, имя загружаемого файла и краткую статистику по созданным/измененным объектам. Это позволит быстро провести расследование в случае инцидентов ИБ.

Мы подробно разобрали, как реализовать загрузку данных XML под ограниченными правами в 1С. Использование привилегированных общих модулей и фоновых заданий позволяет элегантно обойти ограничения прав платформы, сохраняя при этом удобство для конечного пользователя. Главное — помнить о правилах безопасности и не оставлять брешей для несанкционированного изменения конфиденциальных данных вашей информационной системы.

← На главную