Как узнать в коде 1С 8, под кем работает сеанс: клиент, сервер, фоновые задания
Содержание
Самый быстрый способ получить текущего пользователя в 1С 8 — функция глобального контекста ИмяПользователя(). Она работает и на клиенте, и на сервере и возвращает строку с именем. Если нужен сам объект пользователя с GUID, ролями и способом входа, на сервере вызывайте ПользователиИнформационнойБазы.ТекущийПользователь().
Частое заблуждение — считать, что имя и есть «пользователь». Имя администратор может переименовать в любой момент, и все ссылки на старое имя в регистрах и логах перестанут совпадать. Для хранения и сравнения берите уникальный идентификатор, а в типовых конфигурациях на БСП — ссылку на элемент справочника Пользователи.
Три уровня «пользователя» в 1С:Предприятии 8.3
Под словом «пользователь» в 1С скрываются три разные сущности. Путаница между ними — источник половины вопросов на форумах.
- 👤 Пользователь информационной базы — учётная запись платформы. Её видно в Конфигураторе:
Администрирование → Пользователи. В коде это объект типаПользовательИнформационнойБазы. - 📇 Элемент справочника
Пользователи— прикладная карточка в типовых конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11, ERP). С ним связаны ответственные в документах, настройки, доступ. - 💻 Пользователь операционной системы — учётная запись Windows или Linux, под которой запущен клиент или служба сервера 1С.
Связь между первыми двумя хранится в реквизите справочника ИдентификаторПользователяИБ. Там лежит GUID пользователя ИБ. Связь с пользователем ОС есть только при аутентификации операционной системы, и то лишь как строка вида \\ДОМЕН\login.
Функции глобального контекста
| Функция | Что возвращает | Где доступна |
|---|---|---|
ИмяПользователя() | Строка, свойство Имя текущего пользователя | Клиент и сервер |
ПолноеИмяПользователя() | Строка, свойство ПолноеИмя | Клиент и сервер |
ПользователиИнформационнойБазы.ТекущийПользователь() | Объект ПользовательИнформационнойБазы | Сервер, толстый клиент, внешнее соединение |
РольДоступна("ИмяРоли") | Булево: есть ли у текущего пользователя роль | Клиент и сервер |
Менеджер ПользователиИнформационнойБазы в тонком и веб-клиенте недоступен. Это главное ограничение, о котором ниже подробнее.
Клиент и сервер: где какой метод работает
В управляемом приложении код формы делится по директивам компиляции. Тонкий клиент не видит серверных объектов, поэтому один и тот же вызов ведёт себя по-разному.
На клиенте
Если нужно только имя — сервер не нужен:
&НаКлиенте
Процедура ПоказатьИмя(Команда)
Сообщить("Вы вошли как: " + ИмяПользователя());
Сообщить("Полное имя: " + ПолноеИмяПользователя());
КонецПроцедуры
Попытка обратиться к ПользователиИнформационнойБазы прямо в &НаКлиенте в тонком клиенте даст ошибку при проверке модуля: переменная не определена.
На сервере
Объект пользователя получают в серверной процедуре. Если данные формы не нужны, используйте &НаСервереБезКонтекста — вызов не гонит форму на сервер и работает быстрее:
&НаСервереБезКонтекста
Функция ДанныеТекущегоПользователя()
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Результат = Новый Структура;
Результат.Вставить("Имя", ПользовательИБ.Имя);
Результат.Вставить("ПолноеИмя", ПользовательИБ.ПолноеИмя);
Результат.Вставить("GUID", Строка(ПользовательИБ.УникальныйИдентификатор));
Результат.Вставить("АутентификацияОС", ПользовательИБ.АутентификацияОС);
Результат.Вставить("ПользовательОС", ПользовательИБ.ПользовательОС);
Возврат Результат;
КонецФункции
&НаКлиенте
Процедура ПоказатьДанные(Команда)
Данные = ДанныеТекущегоПользователя();
Сообщить(Данные.Имя + " / " + Данные.GUID);
КонецПроцедуры
Объект ПользовательИнформационнойБазы нельзя вернуть на клиент как есть. Переложите нужные свойства в структуру, как в примере, — структура с примитивными значениями передаётся без проблем.
В типовых конфигурациях на БСП
В Бухгалтерии, ЗУП, УТ и других конфигурациях на Библиотеке стандартных подсистем работайте не с пользователем ИБ, а со ссылкой на справочник. Для этого в БСП есть готовые функции:
| Задача | Сервер | Клиент |
|---|---|---|
| Ссылка на текущего пользователя | Пользователи.ТекущийПользователь() | ПользователиКлиент.ТекущийПользователь() |
| Пользователь или внешний пользователь | Пользователи.АвторизованныйПользователь() | ПользователиКлиент.АвторизованныйПользователь() |
| Полные права | Пользователи.ЭтоПолноправныйПользователь() | — |
// Заполнение ответственного при создании документа
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если Не ЗначениеЗаполнено(Ответственный) Тогда
Ответственный = Пользователи.ТекущийПользователь();
КонецЕсли;
КонецПроцедуры
Внутри БСП текущий пользователь хранится в параметре сеанса ТекущийПользователь. Читать его напрямую можно, но лучше через функцию модуля Пользователи: она учитывает внешних пользователей и случай, когда список пользователей пуст.
Имя, полное имя и GUID: что брать для идентификации
У объекта ПользовательИнформационнойБазы много свойств. Для идентификации важны три.
| Свойство | Пример | Меняется? | Когда использовать |
|---|---|---|---|
Имя | Иванова | Да, при переименовании | Вывод на экран, логин, отбор в журнале регистрации |
ПолноеИмя | Иванова Анна Сергеевна | Да | Печатные формы, подписи |
УникальныйИдентификатор | 5f1c2a7e-… | Нет | Хранение в регистрах, сравнение, связь со справочником |
Где «Код» пользователя
У пользователя ИБ свойства Код нет. Если в задаче фигурирует код, речь о справочнике. В типовых конфигурациях на БСП справочник Пользователи идентифицируют по ссылке и по ИдентификаторПользователяИБ, а не по коду. Если у вас самописная конфигурация со своим справочником сотрудников, код задан там, и получить его можно только через связь с пользователем ИБ.
Поиск элемента справочника по GUID пользователя ИБ:
Функция ЭлементСправочникаПоТекущемуПользователю()
ИдентификаторИБ = ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Пользователи.Ссылка КАК Ссылка
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.ИдентификаторПользователяИБ = &Идентификатор";
Запрос.УстановитьПараметр("Идентификатор", ИдентификаторИБ);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Неопределено;
КонецФункции
В конфигурации на БСП этот запрос писать не нужно — Пользователи.ТекущийПользователь() делает то же самое. Пример пригодится в собственной конфигурации, где связь устроена так же.
GUID сохраняется при выгрузке и загрузке базы через .dt. Если же пользователя удалили и создали заново с тем же именем, GUID будет новым, и старые записи с ним не свяжутся.
Пользователь операционной системы: как узнать логин Windows
Встроенной функции «логин Windows текущего сеанса» в 1С нет. Есть два пути.
Через свойство пользователя ИБ
Если в карточке пользователя включена аутентификация ОС, свойство ПользовательОС хранит привязанную учётную запись:
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Если ПользовательИБ.АутентификацияОС Тогда
ЛогинОС = ПользовательИБ.ПользовательОС; // например, \\OFFICE\ivanova
КонецЕсли;
Это настройка, а не факт. Пользователь мог войти паролем 1С, будучи в системе под другой учётной записью.
Через COM-объект на клиенте (только Windows)
Фактический логин клиента возвращает объект WScript.Network. Вызывайте его на клиенте:
&НаКлиенте
Функция ЛогинWindows()
Попытка
Сеть = Новый COMОбъект("WScript.Network");
Возврат Сеть.UserDomain + "\" + Сеть.UserName;
Исключение
Возврат "";
КонецПопытки;
КонецФункции
Не запускайте этот код на сервере. В клиент-серверном варианте он вернёт учётную запись службы сервера 1С (часто USR1CV8), а не пользователя за компьютером. В веб-клиенте и на Linux COM недоступен — оборачивайте вызов в Попытка.
Имя компьютера клиента даёт функция ИмяКомпьютера(). На клиенте это машина пользователя, на сервере — сервер.
Фоновые и регламентные задания: от чьего имени выполняется код
Здесь ошибаются чаще всего: код, который «всегда работал», в фоне вдруг пишет в документ пустого ответственного.
Фоновое задание из сеанса пользователя
Задание, запущенное через ФоновыеЗадания.Выполнить() из сеанса пользователя, работает от имени этого пользователя. ИмяПользователя() внутри вернёт то же имя, что и в запустившем сеансе. Роли и ограничения доступа тоже его.
Регламентное задание
У регламентного задания есть свойство ИмяПользователя. Если оно заполнено, задание выполняется от имени указанного пользователя ИБ. Если пусто — пользователь не определён, и ИмяПользователя() вернёт пустую строку.
Как проверить, что код выполняется в фоне, и узнать подробности сеанса:
ТекущийСеанс = ПолучитьТекущийСеансИнформационнойБазы();
ЭтоФон = (ТекущийСеанс.ПолучитьФоновоеЗадание() <> Неопределено);
Сообщение = СтрШаблон("Сеанс %1, приложение %2, компьютер %3",
Формат(ТекущийСеанс.НомерСеанса, "ЧГ=0"),
ТекущийСеанс.ИмяПриложения,
ТекущийСеанс.ИмяКомпьютера);
В БСП для пустого пользователя есть специальный элемент справочника «<Не указан>». Его вернёт Пользователи.ТекущийПользователь(), если сеанс работает без пользователя ИБ. Проверяйте результат, прежде чем подставлять его в реквизит «Ответственный».
Если задача должна оставлять след конкретного человека, передайте ссылку на пользователя параметром задания. Не рассчитывайте, что фон «сам узнает», кто нажал кнопку.
Привилегированный режим
УстановитьПривилегированныйРежим(Истина) отключает проверку прав, но пользователя не меняет. ИмяПользователя() в привилегированном режиме возвращает того же человека.
Готовые примеры кода по задачам
Короткие рецепты под частые задачи.
Проверить, что работает администратор:
Если РольДоступна("ПолныеПрава") Тогда
// доступно только администраторам
КонецЕсли;
Список всех ролей текущего пользователя лежит в свойстве Роли объекта пользователя ИБ. Это коллекция объектов метаданных, её удобно обойти циклом при отладке прав:
Для Каждого Роль Из ПользователиИнформационнойБазы.ТекущийПользователь().Роли Цикл
Сообщить(Роль.Имя + " — " + Роль.Синоним);
КонецЦикла;
РольДоступна() удобна для одной проверки в коде, а свойство Роли даёт полный список назначенного — его смотрят, когда разбираются, откуда у пользователя доступ.
Имя роли зависит от конфигурации. В БСП вместо проверки конкретной роли используйте Пользователи.ЭтоПолноправныйПользователь().
Передать текущего пользователя в запрос. В языке запросов нет встроенного параметра «текущий пользователь». Передайте значение сами:
Запрос.УстановитьПараметр("Пользователь", Пользователи.ТекущийПользователь());
Узнать, как пользователь вошёл в базу. Свойства АутентификацияСтандартная, АутентификацияОС и АутентификацияOpenID показывают, какие способы входа разрешены в карточке. Это помогает, например, не предлагать смену пароля тем, кто входит только через Windows:
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
ТолькоВходWindows = ПользовательИБ.АутентификацияОС
И Не ПользовательИБ.АутентификацияСтандартная;
Пользователь во внешнем соединении. При подключении через COM-соединение или 1cv8 /N пользователь задаётся в строке подключения (Usr= и Pwd=). Внутри соединения ИмяПользователя() вернёт именно его. Для интеграций заводят отдельного пользователя ИБ с минимальными ролями — тогда в журнале регистрации сразу видно, что изменения сделал обмен, а не человек.
Записать имя в журнал регистрации. Имя подставлять не нужно: журнал сам фиксирует пользователя каждого события.
ЗаписьЖурналаРегистрации("МояОбработка.Выгрузка",
УровеньЖурналаРегистрации.Информация, , , "Выгрузка завершена");
Отбор списка по текущему пользователю при открытии формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список, "Ответственный", Пользователи.ТекущийПользователь());
КонецПроцедуры
Процедура УстановитьЭлементОтбораДинамическогоСписка есть в модуле БСП. В самописной конфигурации добавьте элемент отбора в Список.Отбор вручную.
ИмяПользователя() или ПолноеИмяПользователя() — без вызова сервера.ПользователиИнформационнойБазы.ТекущийПользователь(), свойства переложить в структуру.Пользователи.ТекущийПользователь() на сервере или ПользователиКлиент.ТекущийПользователь() на клиенте.WScript.Network на клиенте в Попытка; на сервере не вызывать.Типичные ошибки при получении пользователя
- ❌ Сравнение по имени.
Если ИмяПользователя() = "Иванова"ломается после переименования. Сравнивайте GUID или ссылку справочника. - ❌ Вызов
ПользователиИнформационнойБазына клиенте. В тонком клиенте объект недоступен — нужен серверный вызов. - ❌ Пустой список пользователей. Если в базе нет ни одного пользователя ИБ,
ИмяПользователя()возвращает пустую строку. Код, который ищет пользователя по имени, в такой базе ничего не найдёт. - ❌ Хранение текущего пользователя в общих данных. Кешировать результат в общем модуле с повторным использованием на время сеанса можно: в рамках сеанса пользователь не меняется. А вот константа или регистр сведений «для скорости» общие для всех сеансов — туда текущего пользователя не пишут.
- ❌ Поиск других пользователей без прав.
ПользователиИнформационнойБазы.НайтиПоИмени()иПолучитьПользователей()требуют права администрирования. Для обычного пользователя оберните вызов в привилегированный режим на сервере и верните только нужные поля.
Частые вопросы
Чем ИмяПользователя() отличается от ПолноеИмяПользователя()?
Почему ИмяПользователя() возвращает пустую строку?
Можно ли получить пользователя другого сеанса?
ПолучитьСеансыИнформационнойБазы() возвращает массив сеансов, у каждого есть свойство Пользователь. Для чтения чужих сеансов нужны административные права.Меняется ли GUID пользователя при обновлении конфигурации?
.dt его сохраняют. Новый GUID появляется только у заново созданного пользователя.Можно ли сменить пользователя без перезапуска 1С?
Как узнать пользователя во внешней обработке?
ИмяПользователя() на клиенте, ПользователиИнформационнойБазы.ТекущийПользователь() в серверной процедуре формы обработки.