Текущий пользователь в коде 1С 8.3: имя, объект, ссылка и права
Содержание
Чтобы программно определить текущего пользователя 1С, чаще всего хватает одной строки: ИмяПользователя() возвращает имя, под которым выполнен вход, а ПользователиИнформационнойБазы.ТекущийПользователь() на сервере даёт полный объект с ролями и идентификатором. В типовых конфигурациях на БСП для записи в документы нужна третья вещь — ссылка на элемент справочника Пользователи: её возвращает Пользователи.ТекущийПользователь().
Частая ошибка — считать, что это одно и то же. Имя — строка, которую администратор может переименовать. Объект пользователя ИБ живёт вне справочников. Ссылка на справочник — то, что хранится в реквизите «Ответственный». Ниже каждый способ с примерами для платформы 8.3 и разбор, где какой работает.
Функции глобального контекста: имя пользователя одной строкой
Глобальный контекст платформы даёт две функции. Обе доступны везде: на сервере, в тонком, толстом и веб-клиенте, во внешнем соединении.
| Функция | Что возвращает | Пример результата |
|---|---|---|
ИмяПользователя() | Имя для входа (свойство Имя) | Иванова |
ПолноеИмяПользователя() | Полное имя (свойство ПолноеИмя) | Иванова Мария Петровна |
Минимальный пример в модуле формы:
&НаКлиенте
Процедура ПоказатьПользователя(Команда)
Сообщить("Вы вошли как: " + ИмяПользователя()
+ " (" + ПолноеИмяПользователя() + ")");
КонецПроцедуры
Обе функции возвращают пустую строку, если в базе нет ни одного пользователя. Так бывает в новой файловой базе или в демо-копии. Учитывайте это в коде:
Имя = ИмяПользователя();
Если ПустаяСтрока(Имя) Тогда
Имя = "<без авторизации>";
КонецЕсли;
Для вывода в шапку отчёта или в текст письма берите ПолноеИмяПользователя(). Для логики — никогда не берите ни одно из двух имён, подробнее в разделе об ошибках.
Пользователь информационной базы и пользователь Windows — не одно и то же
В 1С есть три разных «пользователя», и путаница между ними даёт большую часть вопросов.
- 👤 Пользователь информационной базы — учётная запись платформы. Создаётся в Конфигураторе через
Администрирование → Пользователиили из программы. Именно его возвращают функции глобального контекста. - 🗂️ Элемент справочника «Пользователи» — прикладная запись в типовых конфигурациях. Хранит ФИО, физлицо, подразделение, контактную информацию. Связан с пользователем ИБ через реквизит
ИдентификаторПользователяИБ. - 🖥️ Пользователь операционной системы — учётная запись Windows, под которой запущен клиент.
Пользователь ОС участвует только при аутентификации операционной системы. Тогда у пользователя ИБ заполнено свойство ПользовательОС в формате \\ДОМЕН\логин, и платформа пускает его без пароля.
Узнать, под каким пользователем ИБ сопоставлена учётная запись Windows, можно на сервере:
&НаСервереБезКонтекста
Функция ПользовательWindowsИзНастроек()
ТекПользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
Если ТекПользователь.АутентификацияОС Тогда
Возврат ТекПользователь.ПользовательОС; // "\\OFFICE\m.ivanova"
КонецЕсли;
Возврат "";
КонецФункции
Если аутентификация ОС не включена, это свойство пустое. Фактический логин Windows на машине клиента тогда получают средствами самой ОС, например через COM-объект WScript.Network. Это работает только в клиенте под Windows:
&НаКлиенте
Функция ЛогинWindows()
Сеть = Новый COMОбъект("WScript.Network");
Возврат Сеть.UserDomain + "\" + Сеть.UserName;
КонецФункции
В веб-клиенте и на клиентах под Linux и macOS этот код не сработает. Оберните его в Попытка … Исключение или проверяйте тип платформы через СистемнаяИнформация.
Объект ПользовательИнформационнойБазы: свойства, поиск, роли
Полный объект текущего пользователя возвращает менеджер ПользователиИнформационнойБазы. Он доступен на сервере, в толстом клиенте и во внешнем соединении. В тонком и веб-клиенте его нет — вызов надо выносить на сервер.
&НаСервереБезКонтекста
Функция ДанныеТекущегоПользователя()
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Результат = Новый Структура;
Результат.Вставить("Имя", ПользовательИБ.Имя);
Результат.Вставить("ПолноеИмя", ПользовательИБ.ПолноеИмя);
Результат.Вставить("Идентификатор", ПользовательИБ.УникальныйИдентификатор);
Результат.Вставить("ПарольУстановлен", ПользовательИБ.ПарольУстановлен);
Роли = Новый Массив;
Для Каждого Роль Из ПользовательИБ.Роли Цикл
Роли.Добавить(Роль.Имя);
КонецЦикла;
Результат.Вставить("Роли", Роли);
Возврат Результат;
КонецФункции
Свойства, которые нужны чаще всего:
| Свойство | Тип | Зачем |
|---|---|---|
Имя | Строка | Логин, тот же, что в ИмяПользователя() |
ПолноеИмя | Строка | Отображаемое имя |
УникальныйИдентификатор | УникальныйИдентификатор | Стабильный ключ, не меняется при переименовании |
Роли | Коллекция ролей | Набор ролей пользователя |
АутентификацияСтандартная | Булево | Вход по логину и паролю |
АутентификацияОС | Булево | Вход через Windows |
ПользовательОС | Строка | Сопоставленная учётная запись Windows |
Язык | ОбъектМетаданных | Язык интерфейса |
Найти другого пользователя ИБ можно по имени или идентификатору:
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени("Иванова");
// или
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(Ид);
Если ПользовательИБ = Неопределено Тогда
// пользователь не найден
КонецЕсли;
Свой объект ТекущийПользователь() возвращает любому пользователю. А вот поиск чужих учётных записей, ПолучитьПользователей() и любая запись изменений требуют права «Администрирование». Без него получите ошибку недостаточности прав.
Данные текущего сеанса
Если кроме пользователя нужны компьютер, приложение и время входа, возьмите текущий сеанс:
&НаСервереБезКонтекста
Функция ОписаниеСеанса()
Сеанс = ПолучитьТекущийСеансИнформационнойБазы();
Возврат СтрШаблон("%1, компьютер %2, сеанс №%3, вход %4",
Сеанс.Пользователь.Имя,
Сеанс.ИмяКомпьютера,
Формат(Сеанс.НомерСеанса, "ЧГ=0"),
Формат(Сеанс.НачалоСеанса, "ДФ='dd.MM.yyyy HH:mm'"));
КонецФункции
Сеанс.ИмяКомпьютера — имя клиентской машины, даже когда код выполняется на сервере. Это пригодится в клиент-серверном варианте, о котором ниже.
Текущий пользователь в типовых конфигурациях на БСП
Бухгалтерия 3.0, ЗУП 3.1, УТ 11, ERP и другие типовые решения построены на Библиотеке стандартных подсистем. Там в документах хранится не имя, а ссылка на справочник Пользователи. Получают её так:
| Где выполняется код | Вызов | Результат |
|---|---|---|
| Сервер | Пользователи.ТекущийПользователь() | СправочникСсылка.Пользователи |
| Сервер | Пользователи.АвторизованныйПользователь() | Пользователь или внешний пользователь |
| Клиент | ПользователиКлиент.ТекущийПользователь() | СправочникСсылка.Пользователи |
| Клиент | ПользователиКлиент.АвторизованныйПользователь() | Пользователь или внешний пользователь |
АвторизованныйПользователь() нужен там, где в базу заходят внешние пользователи — например, клиенты через личный кабинет. Обычный ТекущийПользователь() для внешнего пользователя вызовет исключение.
Типичное заполнение реквизита при создании документа:
// Модуль объекта документа
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если Не ЗначениеЗаполнено(Ответственный) Тогда
Ответственный = Пользователи.ТекущийПользователь();
КонецЕсли;
КонецПроцедуры
В запросе текущего пользователя передают параметром:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док.Ссылка,
| Док.Дата
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Док
|ГДЕ
| Док.Ответственный = &ТекущийПользователь";
Запрос.УстановитьПараметр("ТекущийПользователь", Пользователи.ТекущийПользователь());
В БСП есть и параметр сеанса ТекущийПользователь, но обращаться к нему напрямую не нужно. Программный интерфейс модуля Пользователи учитывает внешних пользователей и сам заполняет параметр при первом обращении.
Чтобы из ссылки получить пользователя ИБ, прочитайте реквизит ИдентификаторПользователяИБ и передайте его в НайтиПоУникальномуИдентификатору. Обратная связь работает так же.
Если конфигурация написана без БСП
В самописных базах справочника Пользователи может не быть или он устроен иначе. Связь «пользователь ИБ → элемент справочника» тогда делают сами. Надёжный вариант — реквизит с уникальным идентификатором пользователя ИБ (строка длиной 36) и общий модуль с повторным использованием возвращаемых значений.
Создайте общий модуль ТекущийПользовательПовтИсп: флажок «Сервер», повторное использование «На время сеанса».
Функция Ссылка() Экспорт
Ид = Строка(ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Сотр.Ссылка
|ИЗ
| Справочник.Сотрудники КАК Сотр
|ГДЕ
| Сотр.ИдентификаторПользователяИБ = &Ид";
Запрос.УстановитьПараметр("Ид", Ид);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Справочники.Сотрудники.ПустаяСсылка();
КонецФункции
Запрос выполнится один раз за сеанс, дальше платформа вернёт результат из кэша. Имена справочника и реквизита здесь условные — подставьте свои.
Почему не искать по имени: при переименовании пользователя в Конфигураторе связь по строке рвётся молча, а идентификатор остаётся прежним. Если же идентификатор из справочника не находится среди пользователей ИБ, значит, учётную запись удалили и создали заново — привяжите её повторно.
Если в базе нет ни одного пользователя ИБ, БСП возвращает служебный элемент справочника вместо пустой ссылки. Проверяйте результат, если пишете обработку, которая может запускаться в такой базе.
Клиент-серверный вариант, фоновые и регламентные задания
В файловом и клиент-серверном варианте функции работают одинаково. Различается то, где выполняется код, и это меняет часть ответов.
🖥️
ИмяКомпьютера()на сервере вернёт имя сервера 1С, а не компьютера пользователя. Имя клиентской машины берите изПолучитьТекущийСеансИнформационнойБазы().ИмяКомпьютераили вызывайтеИмяКомпьютера()в клиентской процедуре.🔄 Фоновое задание, запущенное из сеанса, выполняется от имени того же пользователя.
ИмяПользователя()внутри него вернёт имя того, кто запустил задание.⏰ Регламентное задание выполняется от имени пользователя, указанного в его настройках. Если поле пустое, имени у сеанса может не быть — проверяйте результат на пустую строку, а не рассчитывайте на конкретного человека.
🔌 Внешнее соединение (COM
V83.COMConnector) работает от имени пользователя из строки подключения. Код внутри видит именно его.🌐 HTTP-сервисы и веб-сервисы выполняются от имени пользователя, который прошёл базовую аутентификацию в запросе, либо от пользователя, заданного в публикации на веб-сервере. Если в логах сервиса везде одно имя, значит, все запросы идут под общей учётной записью из публикации — различать вызывающих придётся по данным самого запроса.
Привилегированный режим (УстановитьПривилегированныйРежим(Истина)) расширяет права, но не меняет пользователя. ИмяПользователя() в нём вернёт то же имя.
Для журналов и аудита не используйте имя компьютера как признак пользователя. В терминальной ферме за одним сервером RDP сидят десятки людей.
ИмяПользователя() или ПолноеИмяПользователя() — работает в любом контексте, вызов сервера не нужен.Пользователи.ТекущийПользователь(), на клиенте ПользователиКлиент.ТекущийПользователь().ПользователиИнформационнойБазы.ТекущийПользователь() в серверной процедуре.ПолучитьТекущийСеансИнформационнойБазы() на сервере.РольДоступна() или ПравоДоступа(), а в БСП — Пользователи.РолиДоступны().Проверка прав доступа текущего пользователя
Определять пользователя ради проверки прав — частый, но неверный путь. Код вида «если имя = Иванова, разрешить» ломается при первом переименовании. Проверяйте роли и права напрямую.
Есть ли у пользователя роль:
Если РольДоступна("ПолныеПрава") Тогда
// действие для администратора
КонецЕсли;
// надёжнее — через метаданные, ошибка в имени роли всплывёт сразу
Если РольДоступна(Метаданные.Роли.ПолныеПрава) Тогда
КонецЕсли;
Есть ли право на объект:
Если Не ПравоДоступа("Изменение", Метаданные.Справочники.Номенклатура) Тогда
ВызватьИсключение "Недостаточно прав для изменения номенклатуры";
КонецЕсли;
В конфигурациях на БСП:
Пользователи.ЭтоПолноправныйПользователь()— есть ли полные права;Пользователи.РолиДоступны("Роль1, Роль2")— доступна ли хотя бы одна из ролей.
Эти функции учитывают особенности БСП, например поставляемые профили групп доступа. В типовых решениях предпочитайте их.
Три правила безопасности, которые стоит соблюдать:
- Определяйте пользователя на сервере. Имя, переданное с клиента параметром, может быть подменено.
- Проверку прав дублируйте на сервере, даже если кнопка на форме уже скрыта.
- Для ограничений на уровне записей используйте RLS и группы доступа, а не условие по имени в запросе.
Частые ошибки при получении пользователя
&НаСервере или &НаСервереБезКонтекста и верните на клиент нужные значения.Пользователи серверный. На клиенте используйте ПользователиКлиент.ТекущийПользователь().Пользователи.АвторизованныйПользователь().УникальныйИдентификатор или ссылку на справочник.НайтиПоИмени и ПолучитьПользователей требуют права «Администрирование». Для чтения без этого права включайте привилегированный режим на сервере точечно и выключайте сразу после.Ещё одна тонкость — кэширование. Если сохранить имя пользователя в переменной модуля приложения, а администратор переименует пользователя, значение обновится только после перезапуска сеанса. Для подписей это не критично, для ключей — критично, поэтому ключом всегда служит идентификатор.
Частые вопросы
Чем ИмяПользователя() отличается от ПолноеИмяПользователя()?
Можно ли получить текущего пользователя в запросе без параметра?
УстановитьПараметр. Внутри шаблонов RLS для этого используют параметры сеанса.Как узнать, кто сейчас работает в базе, кроме меня?
ПолучитьСеансыИнформационнойБазы() и переберите массив: у каждого сеанса есть свойства Пользователь, ИмяКомпьютера и ИмяПриложения. В Конфигураторе тот же список открывается через Администрирование → Активные пользователи.Вернёт ли ИмяПользователя() другое значение в привилегированном режиме?
Как получить ФИО сотрудника, а не пользователя?
ФизическоеЛицо у ссылки из Пользователи.ТекущийПользователь(). Если реквизит не заполнен, связь пользователя с сотрудником в базе не настроена.