Под каким пользователем работает код 1С и можно ли его подменить

· 9 мин

Содержание

Сменить текущего пользователя внутри уже открытого сеанса 1С нельзя: платформа фиксирует его при входе в базу. Получить текущего пользователя можно тремя способами: ИмяПользователя() вернёт строку, ПользователиИнформационнойБазы.ТекущийПользователь() вернёт объект пользователя ИБ, а в конфигурациях на БСП Пользователи.ТекущийПользователь() вернёт ссылку на элемент справочника «Пользователи».

Если же задача — «установить» пользователя, то есть выполнить код от другого имени, решения такие: перезапуск с параметрами /N и /P, внешнее соединение с логином и паролем, регламентное задание с заданным пользователем или привилегированный режим, который снимает проверку прав, но имя не меняет. Всё это относится к платформе 8.3 целиком и не зависит от конфигурации, кроме мест, где упомянута БСП.

Что платформа считает текущим пользователем

Текущий пользователь — это учётная запись из списка пользователей информационной базы, под которой открыт сеанс. Её выбирают в окне входа, передают в командной строке или подставляют автоматически через аутентификацию Windows.

От этой учётной записи зависят:

  • 🔐 набор ролей и, значит, права на объекты;
  • 📋 ограничения на уровне записей (RLS), если они настроены;
  • 🧾 поле «Пользователь» в журнале регистрации;
  • 🖥️ основной интерфейс, язык и настройки форм.

Если в базе нет ни одного пользователя, окно входа не появляется. Тогда текущий пользователь существует, но у него пустое имя, и ИмяПользователя() вернёт пустую строку. Код, который полагается на имя, в такой базе ломается первым.

В типовых конфигурациях (БП 3.0, ЗУП 3.1, УТ 11, ERP) поверх платформенного пользователя есть второй слой — справочник «Пользователи» из Библиотеки стандартных подсистем. Элемент справочника связан с пользователем ИБ через реквизит ИдентификаторПользователяИБ. Отсюда путаница: «пользователь» в коде может означать два разных объекта.

Что вам нужно сделать с текущим пользователем?

Как получить текущего пользователя и прочитать его свойства

Имя строкой: ИмяПользователя() и ПолноеИмяПользователя()

Две глобальные функции работают в любом контексте, включая тонкий клиент:

Имя = ИмяПользователя();            // "Иванова" — имя для входа
Полное = ПолноеИмяПользователя();   // "Иванова Мария Петровна"

Этого достаточно для подписи в шапке формы или для сообщения пользователю. Для ссылок и сравнений строка не годится — об этом ниже.

Объект пользователя ИБ

ПользователиИнформационнойБазы.ТекущийПользователь() возвращает объект типа ПользовательИнформационнойБазы. Менеджер ПользователиИнформационнойБазы доступен на сервере, во внешнем соединении и в толстом клиенте. В тонком клиенте его нет, поэтому код выносят в серверную процедуру:

&НаСервереБезКонтекста
Функция ОписаниеТекущегоПользователя()

    ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();

    Описание = Новый Структура;
    Описание.Вставить("Имя", ПользовательИБ.Имя);
    Описание.Вставить("ПолноеИмя", ПользовательИБ.ПолноеИмя);
    Описание.Вставить("Идентификатор", ПользовательИБ.УникальныйИдентификатор);
    Описание.Вставить("ВходПоПаролю", ПользовательИБ.АутентификацияСтандартная);
    Описание.Вставить("ВходЧерезWindows", ПользовательИБ.АутентификацияОС);

    СписокРолей = Новый Массив;
    Для Каждого Роль Из ПользовательИБ.Роли Цикл
        СписокРолей.Добавить(Роль.Имя);
    КонецЦикла;
    Описание.Вставить("Роли", СписокРолей);

    Возврат Описание;

КонецФункции

Чтение своей собственной записи не требует особых прав. А вот перебор чужих пользователей через ПолучитьПользователей() или НайтиПоИмени() требует права «Администрирование» либо привилегированного режима.

Ссылка на справочник «Пользователи» (БСП)

В конфигурациях на БСП для учётных задач нужен не объект ИБ, а ссылка:

// Общий модуль Пользователи, вызов на сервере
ТекущийПользователь = Пользователи.ТекущийПользователь();
Документ.Ответственный = ТекущийПользователь;

Если в базу заходят внешние пользователи (покупатели, поставщики через личный кабинет), Пользователи.ТекущийПользователь() для них вызывает исключение. Универсальный вариант — Пользователи.АвторизованныйПользователь(): он вернёт ссылку либо на «Пользователи», либо на «Внешние пользователи».

Сведения о сеансе

Иногда нужно знать не только кто, но и откуда зашёл. Для этого есть объект сеанса:

Сеанс = ПолучитьТекущийСеансИнформационнойБазы();
Сообщить(СтрШаблон("%1, сеанс %2, компьютер %3, приложение %4",
    Сеанс.Пользователь.Имя,
    Формат(Сеанс.НомерСеанса, "ЧГ=0"),
    Сеанс.ИмяКомпьютера,
    Сеанс.ИмяПриложения));

Функция серверная. Номер сеанса выводим через Формат, чтобы в числе не появились пробелы-разделители разрядов.

Как выполнить код от имени другого пользователя

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

СпособКогда подходитЧто учесть
Перезапуск с /N и /PПользователь сам переключается на другую учёткуТекущий сеанс закрывается
Внешнее соединение (COM)Обработка-робот, интеграция, выгрузкаТолько Windows, пароль не храните в коде
Регламентное заданиеНочные загрузки, рассылкиПользователь задаётся в свойствах задания
Фоновое заданиеДолгая операция без зависания формыВыполняется от того же пользователя, что и запустил
Привилегированный режимНужно действие сверх прав, но от того же имениИмя и RLS-параметры не меняются

Перезапуск под другим именем

Из клиентского кода сеанс можно завершить и сразу открыть заново с дополнительными параметрами командной строки:

&НаКлиенте
Процедура ВойтиПодДругимИменем(Команда)
    ЗавершитьРаботуСистемы(Ложь, Истина, "/N""Склад"" /WA-");
КонецПроцедуры

Параметр /WA- отключает вход через Windows, иначе платформа может снова подставить доменную учётку. Пароль лучше не передавать: окно входа спросит его само.

Тот же приём работает из ярлыка:

"C:\Program Files\1cv8\common\1cestart.exe" ENTERPRISE /F"D:\Bases\Trade" /N"Склад" /WA-

Внешнее соединение

Обработка в одной базе открывает соединение с другой (или с той же) под служебным пользователем:

Коннектор = Новый COMОбъект("V83.COMConnector");
СтрокаСоединения = "Srvr=""srv1c"";Ref=""trade"";Usr=""Робот"";Pwd=""" + ПарольРобота + """";
Соединение = Коннектор.Connect(СтрокаСоединения);
Сообщить(Соединение.ИмяПользователя());

Для файловой базы вместо Srvr и Ref указывают File=""D:\Bases\Trade"". ПарольРобота берите из защищённого хранилища или параметров запуска, а не из текста модуля: модуль видит любой, кто откроет Конфигуратор.

Регламентное задание с заданным пользователем

Пользователя для регламентного задания можно установить программно:

Задание = РегламентныеЗадания.НайтиПредопределенное(Метаданные.РегламентныеЗадания.ЗагрузкаКурсовВалют);
Задание.ИмяПользователя = "Робот";
Задание.Записать();

Имя объекта метаданных здесь условное — подставьте своё. Если ИмяПользователя пустое, задание выполняется от имени пользователя без имени, а при наличии списка пользователей это часто заканчивается ошибкой входа или нехваткой прав.

Привилегированный режим

Когда задача не «стать другим», а «сделать то, на что нет прав», нужен привилегированный режим:

УстановитьПривилегированныйРежим(Истина);
Попытка
    // запись в регистр, на который у оператора нет прав
    Набор.Записать();
Исключение
    УстановитьПривилегированныйРежим(Ложь);
    ВызватьИсключение;
КонецПопытки;
УстановитьПривилегированныйРежим(Ложь);

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

Ещё один способ — флаг «Привилегированный» в свойствах общего модуля. Все процедуры такого модуля выполняются без проверки прав. Удобно, но держите в нём только узкие функции, а не всё подряд.

Безопасный режим: что в нём нельзя

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

УстановитьБезопасныйРежим(Истина);
Выполнить(ТекстФормулы);

В безопасном режиме:

  • 🚫 включить привилегированный режим нельзя;
  • 🚫 запрещены COM-объекты, внешние компоненты и работа с файлами на сервере;
  • 🚫 нельзя запустить внешнее приложение.

Отсюда практический вывод: ни перезапуск под другим именем, ни внешнее соединение, ни повышение прав из безопасного режима не сработают. Проверить состояние помогает функция БезопасныйРежим().

Код, который выполняется в безопасном режиме, не может его снять: вызов УстановитьБезопасныйРежим(Ложь) для режима, включённого уровнем выше, вызывает исключение. Сам режим снимается при выходе из процедуры, где его включили. Так задумано, чтобы чужой код не отключил ограничение.

В БСП внешние обработки дополнительно проходят через профили безопасности кластера. Если профиль не разрешает, например, доступ к каталогу, никакие права пользователя этого не исправят.

Строка или ссылка: почему важен тип

Самая частая ошибка — хранить пользователя строкой:

Документ.Автор = ИмяПользователя();   // плохо

Что с этим не так:

  • ✏️ администратор переименовал «Иванова» в «Петрова» после замужества — старые документы потеряли связь;
  • 👥 два сотрудника с одинаковым полным именем в отчёте сливаются в одну строку;
  • 🔍 отбор по строке работает медленнее и чувствителен к регистру и пробелам.
Что получаемТипДля чего
ИмяПользователя()СтрокаВывод на экран, сообщения
ПользователиИнформационнойБазы.ТекущийПользователь()ПользовательИнформационнойБазыРоли, способ входа, администрирование
.УникальныйИдентификаторУникальныйИдентификаторСвязь со справочником, поиск
Пользователи.ТекущийПользователь() (БСП)СправочникСсылка.ПользователиРеквизиты документов, отборы, отчёты

Перейти от объекта ИБ к справочнику и обратно можно через идентификатор:

ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(
    Ссылка.ИдентификаторПользователяИБ);
Если ПользовательИБ = Неопределено Тогда
    // у элемента справочника нет учётной записи для входа
КонецЕсли;

Сравнивать строку со ссылкой бессмысленно: условие ИмяПользователя() = Документ.Ответственный всегда ложно, ошибки при этом не будет.

Создание пользователя и выдача ролей из кода

Иногда «установить пользователя» значит завести его программно. На голой платформе это делается так:

НовыйПользователь = ПользователиИнформационнойБазы.СоздатьПользователя();
НовыйПользователь.Имя = "Робот";
НовыйПользователь.ПолноеИмя = "Служебный пользователь для обменов";
НовыйПользователь.Пароль = ПарольРобота;
НовыйПользователь.АутентификацияСтандартная = Истина;
НовыйПользователь.ПоказыватьВСпискеВыбора = Ложь;
НовыйПользователь.Роли.Добавить(Метаданные.Роли.ПолныеПрава);
НовыйПользователь.Записать();

Нужно право «Администрирование». Имя роли ПолныеПрава есть в типовых конфигурациях; в своей подставьте нужную.

В конфигурациях на БСП не создавайте пользователей ИБ напрямую. Справочник «Пользователи» о такой учётке не узнает, группы доступа не применятся, и человек либо не увидит данных, либо увидит лишнее. Заводите элемент справочника, а учётную запись для входа создавайте через его карточку или механизмы самой БСП.

Права в типовых конфигурациях выдают не ролями напрямую, а группами доступа: Администрирование → Настройки пользователей и прав. Добавление роли кодом в обход групп при следующей обработке прав может быть отменено.

Как отследить, кто и что сделал

Журнал регистрации сам записывает пользователя в каждое событие: вход, запись объекта, ошибку. Свои события добавляют так:

ЗаписьЖурналаРегистрации("Обмен.Загрузка",
    УровеньЖурналаРегистрации.Информация,
    Метаданные.Документы.РеализацияТоваровУслуг,
    Документ.Ссылка,
    СтрШаблон("Загружено строк: %1", Формат(КоличествоСтрок, "ЧГ=0")));

Пользователь в записи будет тем, под кем идёт сеанс. Поэтому регламентному заданию и обменам стоит дать отдельную учётку вроде «Робот»: в журнале сразу видно, что документ поменял не человек.

Что помогает при разборе:

  • 📌 фильтр журнала по пользователю и по событию «Данные. Изменение»;
  • 📌 собственные имена событий с префиксом подсистемы, чтобы их легко найти;
  • 📌 в БСП — подсистема версионирования объектов: она хранит, кто и какие реквизиты изменил.

Привилегированный режим авторства не скрывает. Если под «Ивановой» запись прошла в обход прав, в журнале всё равно будет «Иванова».

Ошибки при работе с текущим пользователем

Диагностика: выберите симптом

Ещё одна тихая ошибка — сохранять результат ИмяПользователя() в переменной модуля приложения и потом использовать её после перезапуска с другим именем. Получайте пользователя в момент, когда он нужен, а не один раз при старте.

Частые вопросы

Можно ли в 1С программно войти под другим пользователем без пароля?
Нет, если у этой учётки установлен пароль или вход через Windows для другого домена. Обход пароля платформа не предусматривает. Для служебных задач заведите отдельного пользователя и запускайте под ним регламентное задание.
Как узнать, что текущий пользователь — администратор?
Проверьте право: ПравоДоступа("Администрирование", Метаданные). В конфигурациях на БСП короче: Пользователи.ЭтоПолноправныйПользователь().
Под каким пользователем выполняется фоновое задание?
Под тем же, кто его запустил. Права и ограничения RLS у него те же, что у инициатора.
Можно ли поменять параметр сеанса ТекущийПользователь в БСП?
Технически присвоить значение в привилегированном режиме можно, но делать этого не стоит. На этот параметр опираются ограничения доступа к записям, и человек начнёт видеть чужие данные.
Чем ИмяПользователя() отличается от ПользовательОС?
ИмяПользователя() — имя учётки в базе 1С. Свойство ПользовательОС у пользователя ИБ — доменная учётка Windows вида \\DOMAIN\ivanova, к которой привязан вход без пароля.