Кто сейчас работает в базе: имя, роли и сеанс пользователя в 1С 8.3

· 9 мин

Содержание

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

Это механизмы платформы 8.3, они одинаковы для всех конфигураций. Различаются только функции БСП: их нет в нетиповых решениях без этой библиотеки. Ниже — какой метод выбрать в зависимости от того, где выполняется код и что именно нужно получить.

Три уровня: глобальные функции, пользователь ИБ и справочник «Пользователи»

В 1С есть три разных «пользователя», и путаница между ними — главный источник ошибок в коде.

  • 👤 Имя входа. Строка, которую человек выбирает в окне авторизации. Её возвращают ИмяПользователя() и ПолноеИмяПользователя().
  • 🔐 Пользователь информационной базы. Объект платформы ПользовательИнформационнойБазы: имя, пароль, роли, привязка к Windows. Хранится в служебных таблицах, а не в справочнике.
  • 📇 Элемент справочника «Пользователи». Обычная ссылка, которую ставят в реквизит «Ответственный» или «Автор» документа. Есть только в конфигурациях на БСП, связана с пользователем ИБ через его уникальный идентификатор.

Простейший пример на клиенте:

&НаКлиенте
Процедура ПоказатьПользователя(Команда)
    Сообщить(СтрШаблон("Вход выполнен как: %1 (%2)",
        ИмяПользователя(), ПолноеИмяПользователя()));
КонецПроцедуры

Для типовой конфигурации, где нужно заполнить реквизит документа:

// Модуль объекта документа
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    Если Не ЗначениеЗаполнено(Ответственный) Тогда
        Ответственный = Пользователи.ТекущийПользователь();
    КонецЕсли;
КонецПроцедуры

Без программирования список всех, кто сейчас в базе, администратор видит в Конфигураторе: Администрирование → Активные пользователи.

Что хранит объект ПользовательИнформационнойБазы

ПользователиИнформационнойБазы.ТекущийПользователь() возвращает объект со всеми настройками учётной записи. Самые полезные свойства:

СвойствоЧто содержитЗачем в коде
ИмяИмя для входаВывод, журналы
ПолноеИмяПолное имя (ФИО)Подписи в печатных формах
УникальныйИдентификаторНеизменяемый GUIDНадёжная связь с другими данными
РолиКоллекция назначенных ролейПроверка набора прав
АутентификацияСтандартнаяВход по логину и паролюАудит настроек
АутентификацияОСВход через WindowsАудит настроек
ПользовательОСПривязка к учётке Windows, вида \\ДОМЕН\логинСверка с доменом
ПарольУстановленЗадан ли парольКонтроль пустых паролей
Язык, ОсновнойИнтерфейсЯзык и интерфейсНастройка формы

Функция, которая собирает всё это в структуру и передаёт на клиент:

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

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

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

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

    Возврат Результат;

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

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

Не сравнивайте пользователей по имени. Администратор может переименовать «Иванова» в «Иванов И.И.», и все сохранённые строки перестанут совпадать. Храните УникальныйИдентификатор, он не меняется.

Для проверки одной конкретной роли перебор коллекции не нужен. Есть глобальная функция РольДоступна("ИмяРоли"), она работает и на клиенте. А ПравоДоступа("Изменение", Метаданные.Документы.РеализацияТоваровУслуг) отвечает, есть ли у текущего пользователя право на конкретный объект.

Где выполняется код: клиент или сервер

Набор доступных функций зависит от контекста. Это частая причина ошибки «Процедура или функция с указанным именем не определена» при переносе кода из модуля объекта в модуль формы.

  • 🖥 На сервере доступно всё: глобальные функции, ПользователиИнформационнойБазы, параметры сеанса, Пользователи.ТекущийПользователь() из БСП.
  • 💻 На клиенте (тонком и веб) есть ИмяПользователя(), ПолноеИмяПользователя(), РольДоступна(). Менеджера ПользователиИнформационнойБазы там нет.
  • 🧱 Толстый клиент обычного приложения может обращаться к ПользователиИнформационнойБазы напрямую, но такой код не переносится в управляемые формы.

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

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ИдентификаторПользователя = Строка(
        ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор);
КонецПроцедуры

В БСП для клиента есть готовые функции модуля ПользователиКлиент: ТекущийПользователь(), АвторизованныйПользователь(), ЭтоПолноправныйПользователь(). Они берут значения из параметров работы клиента, которые заполняются при запуске, и обходятся без лишнего обращения к серверу.

Отдельно о параметрах сеанса. В БСП есть ПараметрыСеанса.ТекущийПользователь, но читать его напрямую не стоит. Порядок его установки — внутренняя кухня библиотеки, а программный интерфейс Пользователи.ТекущийПользователь() сохраняется между версиями.

Логин Windows, имя компьютера и номер сеанса

Имя пользователя операционной системы платформа не отдаёт отдельной функцией. Есть два разных вопроса, и ответы на них разные.

С какой учёткой Windows связан пользователь 1С

Это свойство ПользовательОС у объекта пользователя ИБ. Оно заполнено, только если в карточке пользователя включена аутентификация операционной системы. Работает на сервере.

Под какой учёткой Windows сейчас запущен клиент

Здесь нужен COM-объект WScript.Network, и вызывать его надо на клиенте:

&НаКлиенте
Функция УчетнаяЗаписьWindows()

    #Если ВебКлиент Тогда
        Возврат "";
    #Иначе
        Попытка
            Сеть = Новый COMОбъект("WScript.Network");
            Возврат Сеть.UserDomain + "\" + Сеть.UserName;
        Исключение
            Возврат "";
        КонецПопытки;
    #КонецЕсли

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

Тот же код на сервере вернёт не логин бухгалтера, а учётную запись службы сервера 1С (часто это USR1CV8). Отсюда «у всех пользователей одинаковый логин» в журналах.

COM работает только в Windows. На клиенте под Linux или macOS функция вернёт пустую строку, и это нормальное поведение.

Компьютер и сеанс

Имя компьютера даёт глобальная функция ИмяКомпьютера(). Полную картину по текущему подключению возвращает серверная функция ПолучитьТекущийСеансИнформационнойБазы():

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

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

    Возврат СтрШаблон("Пользователь %1, сеанс %2, компьютер %3, приложение %4, вход %5",
        Сеанс.Пользователь.Имя,
        Формат(Сеанс.НомерСеанса, "ЧГ=0"),
        Сеанс.ИмяКомпьютера,
        ПредставлениеПриложения(Сеанс.ИмяПриложения),
        Формат(Сеанс.НачалоСеанса, "ДФ='dd.MM.yyyy HH:mm'"));

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

Формат(..., "ЧГ=0") убирает пробел-разделитель из номера сеанса: без него номер 12345 превратится в «12 345».

Тонкий клиент, веб-клиент и внешнее соединение

Код, который отлично работает в тонком клиенте, может молча отдать пустую строку в браузере. Разберём каждый режим.

Тонкий клиент. Глобальные функции работают, COM доступен в Windows. Всё, что связано с пользователем ИБ, получаем серверным вызовом.

Веб-клиент. ИмяПользователя() и РольДоступна() работают как обычно. COM-объектов нет, поэтому логин Windows через WScript.Network не получить. Если для публикации настроен вход через Windows, привязку берите из свойства ПользовательОС на сервере. Блоки, недоступные в браузере, отсекайте инструкцией препроцессора #Если ВебКлиент Тогда.

Внешнее соединение (COM-коннектор V83.COMConnector). Вызывающая программа подключается под пользователем из строки соединения, параметр Usr. Код внутри базы видит именно его, и ИмяПользователя() вернёт это имя. Для интеграций заведите отдельного пользователя вроде «Обмен_Сайт»: тогда в журнале регистрации сразу видно, какие изменения пришли из внешней системы.

HTTP-сервисы и веб-сервисы. Пользователь определяется аутентификацией публикации. Если в запросе передан логин и пароль базовой аутентификацией, код сервиса работает от его имени.

Какой способ выбрать: сравнение

СпособЧто возвращаетКлиентСерверКогда использовать
ИмяПользователя()Строку с именем входа✅✅Вывод на экран, журналы
ПолноеИмяПользователя()Строку с полным именем✅✅Подписи, заголовки
ПользователиИнформационнойБазы.ТекущийПользователь()Объект пользователя ИБтолько толстый✅Роли, GUID, способ входа
Пользователи.ТекущийПользователь() (БСП)Ссылку на справочник «Пользователи»—✅Реквизиты документов
ПользователиКлиент.ТекущийПользователь() (БСП)Ту же ссылку✅—Код формы без серверного вызова
ПолучитьТекущийСеансИнформационнойБазы()Сеанс: номер, компьютер, приложение—✅Аудит, диагностика
COMОбъект("WScript.Network")Логин WindowsWindows, не веб—Сверка с доменной учёткой

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

Права доступа: что ломается и как это обойти

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

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

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

Если код должен работать по-разному для разных людей, проверяйте роль (РольДоступна), а не имя. Список имён в коде устаревает при первом же кадровом изменении.

Пользователь в регламентных и фоновых заданиях

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

Что из этого следует для кода:

  1. Если пользователь в задании указан, ИмяПользователя() и ПользователиИнформационнойБазы.ТекущийПользователь() вернут его. Права задания равны правам этого пользователя.
  2. Если поле пустое, ИмяПользователя() вернёт пустую строку. Код должен это переживать, а не падать на поиске пользователя по имени.
  3. Фоновое задание, запущенное через ФоновыеЗадания.Выполнить(), работает от имени того, кто его запустил. Поэтому длительная операция, начатая бухгалтером из формы, пишет в журнал его имя.
  4. Заполнять «Ответственного» в документах, созданных заданием, лучше явно: заведите для заданий отдельного пользователя, например «Регламент», и укажите его в свойствах задания.

Шаблон процедуры, которая фиксирует исполнителя в журнале регистрации:

Процедура ОбработкаЗаказовРегламент() Экспорт

    Исполнитель = ИмяПользователя();
    Если ПустаяСтрока(Исполнитель) Тогда
        Исполнитель = "<пользователь не указан>";
    КонецЕсли;

    ЗаписьЖурналаРегистрации("Обработка заказов",
        УровеньЖурналаРегистрации.Информация, , ,
        "Запуск от имени: " + Исполнитель);

    // основная логика задания

КонецПроцедуры

В типовых конфигурациях процедура регламентного задания начинается с вызова ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(). Его оставляйте первой строкой и в своих заданиях, сделанных по образцу БСП.

Не назначайте заданию пользователя с полными правами «на всякий случай». Если задание загружает данные извне, ошибка в нём сможет изменить что угодно. Дайте ему ровно те роли, которые нужны.

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

Чем ИмяПользователя() отличается от ПолноеИмяПользователя()?
Первая возвращает имя для входа, например «Иванова». Вторая — поле «Полное имя» из карточки, например «Иванова Мария Петровна».
Как узнать текущего пользователя в запросе?
В тексте запроса такой функции нет. Получите ссылку в коде и передайте параметром: Запрос.УстановитьПараметр(“ТекущийПользователь”, Пользователи.ТекущийПользователь()).
Можно ли определить пользователя в обработчике события подписки?
Да. Подписка выполняется на сервере в сеансе того, кто записывает объект, поэтому серверные функции вернут его. Для документов, записанных обменом, это будет пользователь, под которым работает обмен.
Как получить пользователя, который последним изменил документ?
Это вопрос не о текущем сеансе, а об истории. Смотрите журнал регистрации с отбором по объекту: в нём для каждой записи указан пользователь и компьютер.
Почему в журнале регистрации пользователь пустой?
Действие выполнено без авторизации: в базе нет пользователей, либо регламентное задание запущено без указания пользователя в его свойствах.