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

· 9 мин

Содержание

Чтобы программно определить текущего пользователя 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") — доступна ли хотя бы одна из ролей.

Эти функции учитывают особенности БСП, например поставляемые профили групп доступа. В типовых решениях предпочитайте их.

Три правила безопасности, которые стоит соблюдать:

  1. Определяйте пользователя на сервере. Имя, переданное с клиента параметром, может быть подменено.
  2. Проверку прав дублируйте на сервере, даже если кнопка на форме уже скрыта.
  3. Для ограничений на уровне записей используйте RLS и группы доступа, а не условие по имени в запросе.

Частые ошибки при получении пользователя

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

Ещё одна тонкость — кэширование. Если сохранить имя пользователя в переменной модуля приложения, а администратор переименует пользователя, значение обновится только после перезапуска сеанса. Для подписей это не критично, для ключей — критично, поэтому ключом всегда служит идентификатор.

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

Чем ИмяПользователя() отличается от ПолноеИмяПользователя()?
Первая функция возвращает логин из списка выбора при входе, вторая — отображаемое полное имя. Обе берутся из свойств пользователя ИБ.
Можно ли получить текущего пользователя в запросе без параметра?
Нет, языком запросов текущего пользователя не получить. Передайте его параметром через УстановитьПараметр. Внутри шаблонов RLS для этого используют параметры сеанса.
Как узнать, кто сейчас работает в базе, кроме меня?
На сервере вызовите ПолучитьСеансыИнформационнойБазы() и переберите массив: у каждого сеанса есть свойства Пользователь, ИмяКомпьютера и ИмяПриложения. В Конфигураторе тот же список открывается через Администрирование → Активные пользователи.
Вернёт ли ИмяПользователя() другое значение в привилегированном режиме?
Нет. Привилегированный режим снимает проверку прав, но сеанс остаётся за тем же пользователем.
Как получить ФИО сотрудника, а не пользователя?
В типовых конфигурациях возьмите реквизит ФизическоеЛицо у ссылки из Пользователи.ТекущийПользователь(). Если реквизит не заполнен, связь пользователя с сотрудником в базе не настроена.