Текущий пользователь в клиентском коде 1С 8.3: имя, UUID и ссылка на справочник

· 9 мин

Содержание

Чтобы получить пользователя на клиенте 1С, вызовите глобальную функцию ИмяПользователя(): она работает в процедурах с директивой &НаКлиенте, в тонком и веб-клиенте, без обращения к серверу. Полное имя возвращает ПолноеИмяПользователя(). Всё остальное (UUID, роли, ссылку на элемент справочника) придётся брать через сервер или из параметров клиента.

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

Где выполняется код: клиент, сервер и почему это важно

В управляемом приложении модуль формы делится на части, и каждая выполняется в своём месте. Директива перед процедурой определяет, какие объекты платформы ей доступны.

ДирективаГде выполняетсяДоступ к данным формыДоступ к базе
&НаКлиентена компьютере пользователя или в браузереданет
&НаСерверена сервере 1Сда, форма передаётся на серверда
&НаСервереБезКонтекстана сервере 1Снетда
&НаКлиентеНаСервереБезКонтекстатам, откуда вызвалинеттолько если вызвали на сервере

Из этого вытекает главное правило темы:

  • 🖥️ на клиенте доступны функции глобального контекста, которые платформа помечает как клиентские, — среди них ИмяПользователя() и ПолноеИмяПользователя();
  • 🗄️ менеджер ПользователиИнформационнойБазы, параметры сеанса, запросы и чтение справочников живут на сервере;
  • 🔁 каждый переход клиент → сервер — это вызов по сети. В веб-клиенте и при работе через интернет он заметно дороже, чем в локальной сети.

Директива &НаСервереБезКонтекста для получения данных о пользователе почти всегда лучше, чем &НаСервере: на сервер не уходят реквизиты формы, вызов легче.

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

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

&НаКлиенте
Процедура ВзятьВРаботу(Команда)
	
	Имя = ИмяПользователя();            // имя для входа, например "ivanova"
	Представление = ПолноеИмяПользователя(); // "Иванова Мария Петровна"
	
	Объект.Комментарий = СтрШаблон("Взято в работу: %1", Представление);
	
КонецПроцедуры

Чем отличаются функции:

ФункцияЧто возвращаетГде задаётся
ИмяПользователя()свойство «Имя» пользователя ИБ — то, что вводят в окне входаКонфигуратор: Администрирование → Пользователи, поле «Имя»
ПолноеИмяПользователя()свойство «Полное имя»там же, поле «Полное имя»

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

Имя пользователя ИБ можно переименовать. Если вы сохраняете его в реквизит документа, через год там может оказаться имя, которого в базе уже нет. Для связи с данными храните ссылку на элемент справочника или UUID.

ПользователиИнформационнойБазы на клиенте: почему не работает и как обойти

В тонком и веб-клиенте менеджер ПользователиИнформационнойБазы недоступен. Код вида:

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

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

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

Рабочая схема — серверная функция, которая собирает нужные свойства в структуру:

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

&НаКлиенте
Процедура ПоказатьПользователя(Команда)
	
	Данные = ДанныеТекущегоПользователя();
	Сообщить(СтрШаблон("%1 (%2)", Данные.ПолноеИмя, Данные.Имя));
	
КонецПроцедуры

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

Права на чтение пользователей ИБ

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

&НаСервереБезКонтекста
Функция ПолноеИмяПоИмени(ИмяДляВхода)
	
	УстановитьПривилегированныйРежим(Истина);
	ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяДляВхода);
	
	Если ПользовательИБ = Неопределено Тогда
		Возврат "";
	КонецЕсли;
	
	Возврат ПользовательИБ.ПолноеИмя;
	
КонецФункции

Не возвращайте на клиент списки ролей, признаки входа и прочие сведения о чужих учётных записях без необходимости — привилегированный режим снимает проверку прав, и ответственность за утечку данных лежит на коде.

Как получить UUID пользователя на клиенте

Уникальный идентификатор — самый надёжный ключ пользователя ИБ: он не меняется при переименовании и смене полного имени. На клиенте прямой функции для него нет, поэтому только через сервер.

Минимальный вариант:

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

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	ИдПользователя = ИдентификаторТекущегоПользователя();
	// тип значения — УникальныйИдентификатор, его можно хранить в реквизите формы
КонецПроцедуры

Если UUID нужен часто — в нескольких формах, в обработчиках ожидания, — не вызывайте сервер каждый раз. Вынесите функцию в общий модуль с настройками:

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

Первый вызов уйдёт на сервер, повторные в том же сеансе вернут сохранённое значение. Для данных о текущем пользователе это безопасно: они не меняются, пока сеанс жив.

Строковое представление UUID получают через Строка(Идентификатор), обратное преобразование — Новый УникальныйИдентификатор(Строка). Удобно для записи в журнал или передачи во внешнюю систему.

Пользователь в типовых конфигурациях на БСП

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

Для клиентского кода в БСП есть готовая функция, которая не делает серверного вызова:

&НаКлиенте
Процедура ЗаполнитьОтветственного(Команда)
	Объект.Ответственный = ПользователиКлиент.ТекущийПользователь();
КонецПроцедуры

Ссылка на текущего пользователя загружается в параметры клиента при запуске программы, поэтому функция отрабатывает мгновенно. На сервере то же самое делает Пользователи.ТекущийПользователь().

Что выбрать в типовой базе:

ЗадачаЧем пользоваться
заполнить реквизит «Ответственный» на клиентеПользователиКлиент.ТекущийПользователь()
то же в серверной процедуреПользователи.ТекущийПользователь()
сеанс может быть у внешнего пользователя (портал, личный кабинет)ПользователиКлиент.АвторизованныйПользователь()
нужна строка для выводаПолноеИмяПользователя()

В сеансе внешнего пользователя функция ТекущийПользователь() вызывает исключение: такого элемента в справочнике «Пользователи» нет, он лежит в справочнике «Внешние пользователи». Если форма открывается и внешними пользователями, работайте через АвторизованныйПользователь() и проверяйте тип ссылки.

В старых редакциях БСП клиентская функция находилась в модуле ПользователиКлиентСервер. Если код из старой обработки не компилируется на новой конфигурации, проверьте, в каком модуле функция объявлена сейчас, — найдите её через поиск по конфигурации (Ctrl+Shift+F в конфигураторе).

Если в конфигурации нет БСП

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

// Общий модуль СотрудникиПовтИсп (Сервер, Вызов сервера, На время сеанса)
Функция ТекущийСотрудник() Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	Сотрудники.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.Сотрудники КАК Сотрудники
	|ГДЕ
	|	Сотрудники.ИдентификаторПользователяИБ = &Идентификатор";
	Запрос.УстановитьПараметр("Идентификатор",
		ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор);
	
	Выборка = Запрос.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		Возврат Выборка.Ссылка;
	КонецЕсли;
	
	Возврат Справочники.Сотрудники.ПустаяСсылка();
	
КонецФункции

На клиенте вызов выглядит так: Объект.Ответственный = СотрудникиПовтИсп.ТекущийСотрудник();. Ссылка вернётся одна на весь сеанс, повторных запросов к базе не будет.

Почему связь по UUID, а не по имени: имя для входа администратор может поменять, например после смены фамилии сотрудника. Привязка по строке тогда тихо отвалится, а по идентификатору — сохранится.

Пустую ссылку на клиенте проверяйте через ЗначениеЗаполнено(): если сотрудник не привязан к учётной записи, покажите сообщение, а не записывайте документ с пустым ответственным.

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

Тонкий клиент, веб-клиент и толстый клиент: в чём разница

ИмяПользователя() и ПолноеИмяПользователя() ведут себя одинаково во всех клиентах. Различия начинаются, когда нужно что-то кроме них.

КлиентПользователиИнформационнойБазы на клиентеЧто учесть
тонкий клиентнедоступенданные — через серверный вызов или параметры клиента
веб-клиентнедоступенкаждый серверный вызов — HTTP-запрос, кэширование особенно важно
толстый клиент, обычное приложениедоступен прямо в клиентском кодекод не переносится в управляемые формы без переделки
толстый клиент, управляемое приложениев модулях управляемых форм — как в тонкомдирективы компиляции обязательны

Имя пользователя Windows

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

  • 🔐 Если у пользователя ИБ включена аутентификация операционной системы, свойство ПользовательОС на сервере вернёт строку вида \\DOMAIN\ivanova. Это самый надёжный путь, он работает и в веб-клиенте.
  • 🪟 В тонком клиенте под Windows можно прочитать имя через COM-объект WScript.Network. Способ не работает в веб-клиенте, на Linux и macOS.
&НаКлиенте
Функция ИмяПользователяWindows()
	
	#Если ВебКлиент Тогда
		Возврат "";
	#Иначе
		Попытка
			Сеть = Новый COMОбъект("WScript.Network");
			Возврат Сеть.UserName;
		Исключение
			Возврат "";
		КонецПопытки;
	#КонецЕсли
	
КонецФункции

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

Пустой список пользователей и другие ошибки

Если в конфигураторе в списке пользователей нет ни одной записи, база запускается без окна входа. В таком режиме:

  • 👤 ИмяПользователя() и ПолноеИмяПользователя() возвращают пустую строку;
  • 🔑 сеанс работает со всеми правами;
  • 📭 найти «текущего» пользователя в списке через НайтиПоИмени не получится — искать нечего.

Поэтому любой код, который опирается на имя, должен проверять пустоту:

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

Проверяйте именно имя, а не UUID: сравнивать идентификатор «пустого» пользователя с чем-то бессмысленно, а ветка с пустым именем читается сразу.

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

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

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

Можно ли получить пользователя в фоновом задании?
Да. Фоновое задание выполняется от имени пользователя, который его запустил, поэтому ИмяПользователя() и ПользователиИнформационнойБазы.ТекущийПользователь() вернут его. Регламентное задание работает от пользователя, указанного в его настройках.
Как узнать, что пользователь — администратор, не вызывая сервер?
В типовых конфигурациях на БСП проверку полноправности выполняют на сервере. На клиенте безопаснее получить признак один раз через серверную функцию с повторным использованием и хранить результат, чем дёргать сервер при каждой проверке.
Чем ИмяПользователя() отличается от ссылки на справочник «Пользователи»?
Первое — строка из списка пользователей ИБ, которую видит платформа. Второе — элемент справочника типовой конфигурации, на который ссылаются документы. Для данных используйте ссылку, для вывода и журналов — строку.
Почему вызов с директивой &НаСервере тормозит форму?
При таком вызове на сервер передаются все данные формы, включая табличные части. Для получения сведений о пользователе контекст формы не нужен — используйте &НаСервереБезКонтекста.
Можно ли сменить пользователя без перезапуска программы?
Нет, пользователь фиксируется при начале сеанса. Чтобы войти под другим, завершите работу и запустите программу заново. Из кода перезапуск выполняет ЗавершитьРаботуСистемы(Ложь, Истина) — второй параметр отвечает за повторный запуск.