Текущий пользователь в 1С 8.3: как получить его в коде, запросе и фоновом задании
Содержание
Найти текущего пользователя в 1С можно тремя способами. На уровне платформы — ПользователиИнформационнойБазы.ТекущийПользователь() на сервере или ИмяПользователя() где угодно, включая клиент. В типовых конфигурациях на БСП — Пользователи.ТекущийПользователь(): он сразу возвращает ссылку на элемент справочника Пользователи, которую можно подставить в документ или запрос.
Какой метод выбрать, зависит от того, что вам нужно: логин для проверки, ФИО для печатной формы или ссылка для отбора. Ниже — разница между ними, примеры кода для 1С:Предприятия 8.3 и ловушки фоновых заданий и веб-клиента.
Два «пользователя» в 1С и какой из них вам нужен
В базе на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11, ERP) у каждого сотрудника две записи:
- 🔐 Пользователь информационной базы — объект платформы. Логин, пароль, роли, способ входа. Хранится вне справочников, в коде это тип
ПользовательИнформационнойБазы. - 📇 Элемент справочника «Пользователи» — обычная ссылка. Её записывают в реквизиты «Ответственный», «Автор», используют в отборах и регистрах.
Связь между ними держится на реквизите ИдентификаторПользователяИБ справочника: там лежит уникальный идентификатор платформенного пользователя.
| Что нужно | Что получать | Метод |
|---|---|---|
| Логин для проверки или лога | Строка | ИмяПользователя() |
| ФИО для печатной формы | Строка | ПолноеИмяПользователя() |
| Роли, способ входа, идентификатор | ПользовательИнформационнойБазы | ПользователиИнформационнойБазы.ТекущийПользователь() |
| Значение для реквизита или запроса | СправочникСсылка.Пользователи | Пользователи.ТекущийПользователь() |
Если конфигурация самописная и справочника пользователей в ней нет, вам доступен только платформенный уровень. Всё про БСП в этом случае пропускайте.
Метод ТекущийПользователь() на уровне платформы
Менеджер ПользователиИнформационнойБазы доступен на сервере, в толстом клиенте и во внешнем соединении. В тонком и веб-клиенте его нет, поэтому код размещают в серверной процедуре.
&НаСервереБезКонтекста
Функция ДанныеТекущегоПользователя()
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Результат = Новый Структура;
Результат.Вставить("Имя", ПользовательИБ.Имя);
Результат.Вставить("ПолноеИмя", ПользовательИБ.ПолноеИмя);
Результат.Вставить("Идентификатор", ПользовательИБ.УникальныйИдентификатор);
Возврат Результат;
КонецФункции
Что ещё полезного есть у объекта ПользовательИнформационнойБазы:
- 🎭
Роли— коллекция назначенных ролей, проверяется черезСодержит(); - 🔑
АутентификацияСтандартная,АутентификацияОС— какие способы входа включены; - 🌐
Язык— язык интерфейса пользователя; - 🆔
УникальныйИдентификатор— не меняется при переименовании логина, поэтому для связей и логов надёжнее имени.
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
ЕстьПолныеПрава = ПользовательИБ.Роли.Содержит(Метаданные.Роли.ПолныеПрава);
Роль ПолныеПрава есть в типовых конфигурациях, но в самописной базе она может называться иначе. Обращение к несуществующей роли через Метаданные.Роли вызовет ошибку — проверьте имя в дереве конфигурации.
Чтобы проверить одну роль, удобнее глобальная функция РольДоступна("ИмяРоли"). Она учитывает роли текущего сеанса, и ей не нужен объект пользователя.
Проверка прав вместо проверки ролей
Часто пользователя определяют только ради вопроса «можно ли ему это». Тогда надёжнее спрашивать не про роль, а про право на конкретный объект:
&НаСервереБезКонтекста
Функция МожноМенятьЦены()
Возврат ПравоДоступа("Изменение", Метаданные.РегистрыСведений.ЦеныНоменклатуры);
КонецФункции
Функция ПравоДоступа() сама учитывает все роли текущего пользователя. Администратор добавит новую роль с нужным правом — код продолжит работать без правок. При проверке через РольДоступна() пришлось бы дописывать каждую новую роль вручную.
Имя регистра в примере условное. Возьмите реальное из дерева метаданных своей конфигурации, иначе получите ошибку при обращении к Метаданные.
Логин и полное имя: ИмяПользователя() и ПолноеИмяПользователя()
Обе функции — глобальный контекст, работают и на сервере, и на клиенте, в том числе в веб-клиенте. Это самый короткий способ узнать, кто сейчас в программе.
&НаКлиенте
Процедура ПоказатьКтоЯ(Команда)
Сообщить("Логин: " + ИмяПользователя());
Сообщить("ФИО: " + ПолноеИмяПользователя());
КонецПроцедуры
Чем различаются два значения:
| Свойство | Пример | Где видно | Для чего |
|---|---|---|---|
| Имя (логин) | ivanova | Окно входа | Проверки в коде, логи, обмены |
| Полное имя | Иванова Анна Сергеевна | Заголовок окна, списки | Печатные формы, сообщения пользователю |
Логин должен быть уникальным в пределах базы. Полное имя — нет: два «Петрова А.» вполне могут существовать одновременно.
Не стройте логику на сравнении с полным именем. Его меняют при смене фамилии, исправлении опечатки, и проверка Если ПолноеИмяПользователя() = "Петров" молча перестанет срабатывать. Для условий берите логин, а ещё лучше — роль или ссылку на справочник.
Когда список пользователей пуст
Если в базе не создано ни одного пользователя, вход выполняется без авторизации. Тогда ИмяПользователя() вернёт пустую строку, а у ПользовательИнформационнойБазы будет пустое имя. Код, который ищет пользователя по имени, в такой базе упадёт или найдёт не того. Добавьте проверку на пустую строку.
Справочник «Пользователи» в типовых конфигурациях
В конфигурациях на БСП не нужно искать элемент справочника вручную по идентификатору. Библиотека даёт готовые функции:
// На сервере
ТекущийПользователь = Пользователи.ТекущийПользователь();
// На клиенте
ТекущийПользователь = ПользователиКлиент.ТекущийПользователь();
Возвращается СправочникСсылка.Пользователи. Её можно сразу записать в реквизит:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Ответственный = Пользователи.ТекущийПользователь();
КонецПроцедуры
Ещё несколько функций того же модуля, которые встречаются на практике:
- 👤
Пользователи.АвторизованныйПользователь()— вернёт ссылку на пользователя или внешнего пользователя, если в базу зашёл контрагент через портал; - 🛡
Пользователи.ЭтоПолноправныйПользователь()— проверка полных прав без обращения к ролям по имени; - 🔎
Пользователи.НайтиПоИмени()и аналоги — поиск в справочнике по логину.
Если внешние пользователи в базе включены, Пользователи.ТекущийПользователь() под внешним пользователем вызовет исключение. В коде, который могут выполнить обе категории, используйте АвторизованныйПользователь().
Параметр сеанса ТекущийПользователь
В типовых конфигурациях есть параметр сеанса с тем же именем. Он заполняется при входе и хранит ту же ссылку. Читать ПараметрыСеанса.ТекущийПользователь напрямую можно, но у обычных ролей прав на параметр может не быть — получите ошибку доступа. Штатная функция БСП эти права обходит корректно.
В старых конфигурациях на платформе 8.2 и обычных формах встречаются глобальные переменные вроде глТекущийПользователь. В современных базах их нет, при переносе кода такие обращения нужно заменить.
Сведения о сеансе: ПолучитьТекущийСеансИнформационнойБазы()
Иногда мало знать пользователя — нужны компьютер, приложение и время входа. Для этого есть объект СеансИнформационнойБазы, он доступен на сервере:
&НаСервереБезКонтекста
Функция ОписаниеСеанса()
Сеанс = ПолучитьТекущийСеансИнформационнойБазы();
Возврат СтрШаблон("%1 | %2 | %3 | сеанс №%4 с %5",
Сеанс.Пользователь.Имя,
Сеанс.ИмяКомпьютера,
Сеанс.ИмяПриложения,
Сеанс.НомерСеанса,
Формат(Сеанс.НачалоСеанса, "ДФ='дд.ММ.гггг ЧЧ:мм'"));
КонецФункции
| Свойство | Что содержит |
|---|---|
Пользователь | Объект ПользовательИнформационнойБазы |
ИмяКомпьютера | Компьютер, с которого подключились |
ИмяПриложения | Тип подключения: тонкий клиент, веб-клиент, фоновое задание, COM-соединение |
НомерСеанса | Номер, по которому сеанс видно в консоли кластера |
НачалоСеанса | Дата и время входа |
Функция ПолучитьСеансыИнформационнойБазы() вернёт массив всех активных сеансов. Так строят собственный список «кто сейчас в базе». В типовых конфигурациях готовая форма уже есть — ищите ссылку «Активные пользователи» в разделе администрирования.
ИмяКомпьютера в веб-клиенте покажет не машину пользователя, а сервер, через который идёт соединение. Для аудита рабочих мест на это поле в веб-клиенте полагаться нельзя.
Текущий пользователь в запросе и отчёте на СКД
В языке запросов нет функции «текущий пользователь». Значение передают параметром:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заказ.Ссылка,
| Заказ.Номер,
| Заказ.СуммаДокумента
|ИЗ
| Документ.ЗаказКлиента КАК Заказ
|ГДЕ
| Заказ.Ответственный = &ТекущийПользователь
| И НЕ Заказ.ПометкаУдаления";
Запрос.УстановитьПараметр("ТекущийПользователь", Пользователи.ТекущийПользователь());
Выборка = Запрос.Выполнить().Выбрать();
Имя документа и реквизита в примере условные — подставьте свои из конфигурации.
Отбор по пользователю в СКД
В схеме компоновки данных добавьте в запрос параметр &ТекущийПользователь. Затем заполните его в модуле объекта отчёта до вывода:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра(
"ТекущийПользователь", Пользователи.ТекущийПользователь());
КонецПроцедуры
На вкладке «Параметры» схемы снимите у параметра флажок доступности пользователю, если подменять его не нужно. Иначе сотрудник откроет настройки и посмотрит чужие заказы.
Ограничение доступа на уровне записей
Если задача — чтобы каждый видел только свои документы, отбор в отчёте не защищает. Его обходят через любой другой список. Правильный путь — ограничение доступа на уровне записей (RLS) в роли. В тексте ограничения параметр сеанса указывается через амперсанд: ГДЕ Ответственный = &ТекущийПользователь. В типовых конфигурациях ограничения строятся механизмом БСП, и правка ролей там — работа разработчика, а не настройка.
Фоновые задания, веб-клиент и внешнее соединение
Здесь чаще всего получают «не того» пользователя.
- ⚙️ Фоновое задание, запущенное из кода, выполняется от имени того, кто его запустил.
ИмяПользователя()внутри вернёт логин инициатора. - 🕒 Регламентное задание выполняется от имени пользователя, указанного в его настройках. Если поле пустое, результат зависит от базы: при отсутствии списка пользователей имя будет пустым. Задайте пользователя явно — так проще читать журнал регистрации.
- 🌐 Веб-клиент и тонкий клиент — серверные объекты недоступны.
ИмяПользователя()иПолноеИмяПользователя()работают на клиенте, а за объектомПользовательИнформационнойБазыидите в серверный вызов. - 🔌 Внешнее соединение и COM — пользователь берётся из строки подключения (
Usr=). Под ним и выполняется весь код. - 📱 HTTP-сервисы — пользователь определяется по авторизации при публикации на веб-сервере.
Привилегированный режим не меняет пользователя. УстановитьПривилегированныйРежим(Истина) отключает проверку прав, но ТекущийПользователь() и журнал регистрации покажут того же сотрудника.
Как передать «настоящего» инициатора в регламентное задание, которое работает под служебным логином? Сохраните ссылку в параметры задания или в регистр при постановке в очередь. Внутри задания определять «кто нажал кнопку» уже поздно.
Готовые примеры и типичные ошибки
Пишем, кто изменил документ
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
ИзменилПользователь = Пользователи.ТекущийПользователь();
ДатаИзменения = ТекущаяДатаСеанса();
КонецПроцедуры
Проверка ОбменДанными.Загрузка нужна, чтобы при обмене не затирать автора из базы-источника логином служебного пользователя обмена.
Безопасное получение ссылки с обработкой ошибок
Функция ТекущийПользовательБезопасно() Экспорт
Попытка
Возврат Пользователи.АвторизованныйПользователь();
Исключение
ЗаписьЖурналаРегистрации("Определение пользователя",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Справочники.Пользователи.ПустаяСсылка();
КонецПопытки;
КонецФункции
Пустая ссылка вместо исключения позволяет документу записаться, а причина остаётся в журнале регистрации.