При разработке интеграционных механизмов и выгрузке файлов на сетевой ресурс часто возникает задача сохранения данных от имени системной службы сервера 1С (обычно USR1CV8), а не текущего пользователя операционной системы. Разберем, почему метод ДвоичныеДанные.Записать() может создавать файлы под учетной записью клиента, и рассмотрим рабочие способы решения этой задачи.
Проанализируем типовую ситуацию: разработчик получает файл из временного хранилища и выполняет сохранение в сетевой каталог следующей конструкцией:
ДвоичныеДанныеВХ = ПолучитьИзВременногоХранилища(АдресВХ);
ДвоичныеДанныеВХ.Записать("\\АдресСервера\папка\" + ИмяФайла);
После выполнения операции владельцем созданного в файловой системе объекта оказывается учетная запись Windows того пользователя, который запустил сеанс 1С. Выясним основные причины такого поведения:
&НаСервере является программной эмуляцией. Весь код фактически выполняется внутри клиентского процесса 1cv8c.exe или 1cv8.exe. Служба сервера 1С в этом сценарии не задействована, поэтому любые файловые операции происходят от имени текущего локального пользователя.&НаКлиенте), запись файла напрямую инициируется рабочей станцией пользователя.Рассмотрим поведение платформы в полноценном клиент-серверном режиме. В среде «клиент-сервер» любой вызов процедуры с директивой &НаСервере или &НаСервереБезКонтекста передается на сервер и обрабатывается рабочим процессом rphost.exe.
Так как процесс rphost.exe работает в контексте системной учетной записи службы 1С (USR1CV8), все операции с файловой системой на стороне сервера автоматически выполняются от имени этой службы.
&НаСервереБезКонтекста
Процедура СохранитьФайлНаСервере(АдресВХ, СетевойПуть, ИмяФайла)
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВХ);
ПолныйПуть = СетевойПуть + "\" + ИмяФайла;
ДвоичныеДанные.Записать(ПолныйПуть);
КонецПроцедуры
Важный нюанс сетевого доступа: по умолчанию учетная запись USR1CV8 является локальным пользователем сервера (.\USR1CV8). Локальный пользователь не имеет доступа к общим сетевым папкам на других серверах домена. Чтобы сервер 1С мог записывать файлы по пути вида \\АдресСервера\папка\, необходимо запускать службу сервера 1С под доменной учетной записью (Domain User) и предоставить ей права NTFS и доступ к общему ресурсу.
Если требуется гарантированно изолировать запись файла от сеанса пользователя и выполнить операцию асинхронно без блокировки интерфейса, используем механизм фоновых заданий через менеджер ФоновыеЗадания.
Разберем реализацию по шагам:
ФоновыеЗадания.Выполнить().Посмотрим на пример реализации серверного модуля:
// Процедура в общем модуле (например, ИнтеграцияФайловСервер)
Процедура ВыгрузитьФайлВКаталог(АдресВХ, ПолноеИмяФайла) Экспорт
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВХ);
ДвоичныеДанные.Записать(ПолноеИмяФайла);
УдалитьИзВременногоХранилища(АдресВХ);
КонецПроцедуры
Вызов фонового задания из формы или обработчика:
&НаКлиенте
Процедура СохранитьФайл(Команда)
// Помещаем файл во временное хранилище на клиенте
АдресФайла = ПоместитьФайлВХранилище();
ЗапуститьФоновоеСохранение(АдресФайла, "Выгрузка.dat");
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ЗапуститьФоновоеСохранение(АдресФайла, ИмяФайла)
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(АдресФайла);
ПараметрыЗадания.Добавить("\\АдресСервера\папка\" + ИмяФайла);
ФоновыеЗадания.Выполнить(
"ИнтеграцияФайловСервер.ВыгрузитьФайлВКаталог",
ПараметрыЗадания,
,
"Выгрузка файла " + ИмяФайла
);
КонецПроцедуры
В распределенных системах или при необходимости работы из файловых баз передачу файлов можно организовать через встроенные HTTP-сервисы 1С:
POST или PUT.HTTPСервисЗапрос.ПолучитьТелоКакДвоичныеДанные()) и сохраняет его в целевой сетевой каталог.Этот подход полностью абстрагирует клиента от файловой системы назначения и гарантирует, что запись в сетевую папку выполняется под учетной записью веб-сервера или пула приложений сервера 1С.
Если изменить архитектуру выгрузки невозможно, скорректировать владельца созданного файла можно системными средствами Windows. Для этого после сохранения файла выполняется команда с помощью метода ЗапуститьПриложение().
Рассмотрим пример использования системных утилит icacls и takeown:
&НаСервере
Процедура СменитьВладельцаФайла(ПутьКФайлу, ИмяНовогоВладельца)
КомандаОС = СтрШаблон("icacls ""%1"" /setowner ""%2"" /T /C /Q", ПутьКФайлу, ИмяНовогоВладельца);
ЗапуститьПриложение(КомандаОС, , Истина);
КонецПроцедуры
Обратите внимание: для успешной смены владельца учетная запись, от имени которой вызывается утилита, должна обладать привилегиями управления безопасностью (SeTakeOwnershipPrivilege или SeRestorePrivilege) в операционной системе.