Текущий пользователь в клиентском коде 1С 8.3: имя, ссылка и права
Содержание
В тонком и веб-клиенте 1С 8.3 имя текущего пользователя возвращают функции глобального контекста ИмяПользователя() и ПолноеИмяПользователя(). Обе работают на клиенте без вызова сервера. Ссылку на элемент справочника «Пользователи» в типовых конфигурациях на БСП даёт ПользователиКлиент.ТекущийПользователь().
А вот ПользователиИнформационнойБазы.ТекущийПользователь() и ПараметрыСеанса в тонком клиенте недоступны. Код с ними в процедуре &НаКлиенте не скомпилируется. Их читают на сервере и передают результат на клиент. Всё ниже касается платформы 8.3 и управляемых форм, конфигурация значения не имеет, если не оговорено отдельно.
Какие способы есть и где они работают
Выбор зависит от того, что именно нужно: строка с именем, объект пользователя информационной базы или ссылка на справочник.
| Способ | Что возвращает | Тонкий и веб-клиент | Нужен вызов сервера |
|---|---|---|---|
ИмяПользователя() | Строка: имя для входа | Да | Нет |
ПолноеИмяПользователя() | Строка: полное имя | Да | Нет |
ПользователиКлиент.ТекущийПользователь() (БСП) | Ссылка на справочник «Пользователи» | Да | Нет, берёт из кэша параметров клиента |
ПользователиИнформационнойБазы.ТекущийПользователь() | Объект ПользовательИнформационнойБазы | Нет | Да |
ПараметрыСеанса.ТекущийПользователь (БСП) | Ссылка на справочник | Нет | Да |
РольДоступна("ИмяРоли") | Булево | Да | Нет |
💡 Если нужно только показать, кто работает, или записать имя в лог на клиенте, хватает ИмяПользователя(). Сервер дёргать незачем.
Имя и полное имя пользователя без обращения к серверу
ИмяПользователя() возвращает имя, под которым человек вошёл в базу. Это то, что видно в окне входа и в списке пользователей Конфигуратора в колонке «Имя». ПолноеИмяПользователя() возвращает поле «Полное имя», обычно ФИО.
&НаКлиенте
Процедура ПоказатьПользователя(Команда)
Имя = ИмяПользователя();
ПолноеИмя = ПолноеИмяПользователя();
Если ПустаяСтрока(Имя) Тогда
Сообщить("В базе нет списка пользователей, вход без авторизации");
Иначе
Сообщить(СтрШаблон("Вы вошли как %1 (%2)", ПолноеИмя, Имя));
КонецЕсли;
КонецПроцедуры
Что важно знать про эти функции:
- 🔹 при входе через аутентификацию Windows возвращается имя пользователя 1С, а не логин Windows;
- 🔹 в фоновом задании возвращается имя пользователя, от которого задание запущено;
- 🔹 в регламентном задании — пользователь, указанный в его свойствах;
- 🔹 если список пользователей пуст, обе функции возвращают пустую строку.
Имя — не идентификатор. Администратор может переименовать пользователя, и всё, что вы сохранили по старому имени, перестанет находиться.
Имя или уникальный идентификатор: что хранить в данных
У каждого пользователя информационной базы есть свойство УникальныйИдентификатор. Оно не меняется при переименовании, смене пароля или полного имени. Имя же можно поменять в любой момент.
| Что сравниваете | Имя | Уникальный идентификатор |
|---|---|---|
| Меняется при переименовании | Да | Нет |
| Доступно на клиенте | Да, ИмяПользователя() | Нет, только на сервере |
| Годится как ключ в регистре или настройке | Нет | Да |
| Удобно для логов и сообщений | Да | Нет, его никто не прочтёт |
В БСП связь хранится в реквизите справочника «Пользователи» ИдентификаторПользователяИБ. Поэтому в типовых конфигурациях в документы пишут ссылку на справочник, а не имя и не идентификатор.
Найти пользователя по сохранённому значению можно только на сервере:
&НаСервереБезКонтекста
Функция ПолноеИмяПоИдентификатору(Идентификатор)
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(Идентификатор);
Если ПользовательИБ = Неопределено Тогда
Возврат "";
КонецЕсли;
Возврат ПользовательИБ.ПолноеИмя;
КонецФункции
Есть и НайтиПоИмени(Имя). Им пользуются, когда на руках только строка из ИмяПользователя().
Поиск произвольных пользователей через ПользователиИнформационнойБазы требует административных прав. Свой объект через ТекущийПользователь() получает любой пользователь.
Как получить ссылку на справочник «Пользователи» с клиента
Чаще всего нужна именно ссылка: подставить ответственного в документ, отфильтровать список «мои заказы», сравнить автора с текущим пользователем.
В конфигурациях на БСП
В БП 3.0, ЗУП 3.1, УТ 11 и других типовых решениях есть клиентский модуль ПользователиКлиент:
&НаКлиенте
Процедура ОтобратьМоиДокументы(Команда)
ТекущийПользователь = ПользователиКлиент.ТекущийПользователь();
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список, "Ответственный", ТекущийПользователь);
КонецПроцедуры
Функция не идёт на сервер. Значение берётся из параметров клиента, которые БСП получает один раз при запуске сеанса. Рядом в том же модуле лежат:
- 🔹
ПользователиКлиент.АвторизованныйПользователь()— вернёт ссылку на внешнего пользователя, если вошёл он; - 🔹
ПользователиКлиент.ЭтоСеансВнешнегоПользователя()— признак сеанса внешнего пользователя.
На сервере то же самое дают Пользователи.ТекущийПользователь() и Пользователи.АвторизованныйПользователь().
Параметры сеанса
БСП при старте сеанса заполняет ПараметрыСеанса.ТекущийПользователь. Читать его можно только в серверном коде. Если у роли нет права на получение этого параметра сеанса, чтение упадёт с ошибкой прав. Поэтому в прикладном коде надёжнее функции модуля Пользователи, чем прямое обращение к параметру.
В своей конфигурации без БСП
Здесь три рабочих приёма.
- Заполнить реквизит формы при её создании. Сервер всё равно вызывается при открытии формы, лишнего обращения не будет:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ТекущийПользовательСсылка = ПараметрыСеанса.ТекущийПользователь;
КонецПроцедуры
- Общий модуль с повторным использованием. Создайте общий модуль с флажками «Сервер» и «Вызов сервера» и с повторным использованием «На время сеанса»:
// Общий модуль ПользовательСеансаПовтИсп
Функция ТекущийПользователь() Экспорт
Возврат ПараметрыСеанса.ТекущийПользователь;
КонецФункции
Первый вызов с клиента идёт на сервер, следующие платформа отдаёт из кэша.
- Свой клиентский кэш. Получите значение один раз в обработчике
ПриНачалеРаботыСистемыи сохраните в глобальную переменную модуля управляемого приложения или в клиентский общий модуль с повторным использованием.
Параметр сеанса ТекущийПользователь сам не заполнится. Его нужно установить в УстановкаПараметровСеанса модуля сеанса: найти элемент справочника по идентификатору пользователя ИБ и записать ссылку.
Тонкий, толстый и веб-клиент: что доступно
Основная путаница возникает из-за толстого клиента. В нём код с ПользователиИнформационнойБазы на клиенте работает, а в тонком падает.
| Объект или функция | Толстый клиент | Тонкий клиент | Веб-клиент |
|---|---|---|---|
ИмяПользователя(), ПолноеИмяПользователя() | Да | Да | Да |
РольДоступна() | Да | Да | Да |
ПользователиИнформационнойБазы | Да | Нет | Нет |
ПараметрыСеанса | Да | Нет | Нет |
Поэтому код, который годами работал в обычном приложении, после перевода на управляемые формы ломается именно на этих строках.
Проверить заранее можно в Конфигураторе. Откройте Конфигурация → Проверка конфигурации, отметьте флажки «Тонкий клиент» и «Веб-клиент». Проверка покажет каждое место, где клиентский код обращается к серверным объектам.
Даже если пользователи сейчас работают в толстом клиенте, пишите клиентский код так, будто это тонкий. Тогда переход не потребует правок.
Пустой пользователь, права и другие ошибки
Пустое значение нужно обрабатывать явно. Если в документ подставляется ответственный, а база открыта без авторизации, лучше оставить поле пустым, чем подставить случайного пользователя:
&НаКлиенте
Процедура ЗаполнитьОтветственного()
Если Не ЗначениеЗаполнено(Объект.Ответственный) Тогда
Пользователь = ПользователиКлиент.ТекущийПользователь();
Если ЗначениеЗаполнено(Пользователь) Тогда
Объект.Ответственный = Пользователь;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Чей пользователь в фоне, в привилегированном режиме и в обработчиках сеанса
Код не всегда выполняется «от имени» того, кто нажал кнопку. Ниже случаи, где результат удивляет чаще всего.
Привилегированный режим
УстановитьПривилегированныйРежим(Истина) снимает проверку прав, но пользователя не меняет. ИмяПользователя() и Пользователи.ТекущийПользователь() внутри такого блока вернут того же человека. Поэтому в журнале регистрации действия в привилегированном режиме записываются на реального пользователя, а не на «администратора».
Фоновые задания
Задание, запущенное через ФоновыеЗадания.Выполнить(), работает в отдельном сеансе от имени пользователя, который его запустил. Параметры сеанса в этом сеансе заполняются заново через УстановкаПараметровСеанса. Клиентского кэша там нет, поэтому ПользователиКлиент в фоне недоступен, только серверный модуль Пользователи.
Регламентные задания
У регламентного задания есть свойство «Пользователь». Если оно заполнено, задание выполняется от имени этого пользователя. Если в коде задания важен автор действий, укажите пользователя явно в свойствах задания: тогда записи в журнале регистрации и реквизиты «Автор» в созданных документах будут понятны при разборе. Пустое свойство оставляйте только для заданий, которым всё равно, от чьего имени они работают.
Обработчики начала работы
В ПриНачалеРаботыСистемы модуля управляемого приложения ИмяПользователя() уже работает. Это удобное место, чтобы один раз получить ссылку на справочник с сервера и положить её в клиентский кэш. В БСП эту работу делают стандартные подсистемы, вмешиваться не нужно.
| Где выполняется код | Чей пользователь | Доступен ПользователиКлиент |
|---|---|---|
| Форма в тонком клиенте | Вошедший пользователь | Да |
| Блок в привилегированном режиме | Тот же вошедший пользователь | Только серверные функции |
| Фоновое задание | Запустивший задание | Нет |
| Регламентное задание (клиент-сервер) | Указанный в свойствах задания | Нет |
| Внешнее соединение | Из строки подключения | Нет |
Практические примеры в клиентском коде
Скрыть кнопку от всех, кроме роли
Права проверяют через роль, а не через имя пользователя. Сравнение с именем ломается при первом же переименовании.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Элементы.ФормаПровестиПринудительно.Видимость = РольДоступна("ПолныеПрава");
КонецПроцедуры
Видимость лучше выставить ещё в ПриСозданииНаСервере, чтобы форма не моргала. Скрытая кнопка — это удобство, а не защита: ограничение всё равно должно стоять в правах роли.
Проверить, что документ редактирует его автор
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Если ЗначениеЗаполнено(Объект.Автор)
И Объект.Автор <> ПользователиКлиент.ТекущийПользователь() Тогда
ПоказатьПредупреждение(, "Изменять документ может только его автор");
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Это подсказка пользователю. Жёсткую проверку продублируйте в ПередЗаписью модуля объекта на сервере: клиентский код можно обойти, например, записью через обработку.
Получить данные пользователя ИБ одним вызовом
Если на клиенте нужны и полное имя, и роли, и признак входа через Windows, соберите всё за один серверный вызов:
&НаСервереБезКонтекста
Функция ДанныеТекущегоПользователя()
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Результат = Новый Структура;
Результат.Вставить("Имя", ПользовательИБ.Имя);
Результат.Вставить("ПолноеИмя", ПользовательИБ.ПолноеИмя);
Результат.Вставить("Идентификатор", ПользовательИБ.УникальныйИдентификатор);
Результат.Вставить("ВходЧерезWindows", ПользовательИБ.АутентификацияОС);
Результат.Вставить("ПользовательОС", ПользовательИБ.ПользовательОС);
Роли = Новый Массив;
Для Каждого Роль Из ПользовательИБ.Роли Цикл
Роли.Добавить(Роль.Имя);
КонецЦикла;
Результат.Вставить("Роли", Роли);
Возврат Результат;
КонецФункции
&НаКлиенте
Процедура ПоказатьСведения(Команда)
Данные = ДанныеТекущегоПользователя();
Сообщить(СтрШаблон("%1, ролей: %2", Данные.ПолноеИмя,
Формат(Данные.Роли.Количество(), "ЧГ=0")));
КонецПроцедуры
Объект ПользовательИнформационнойБазы на клиент передать нельзя: он не сериализуется. Поэтому функция возвращает структуру с простыми значениями, а коллекцию ролей превращает в массив строк.
Частые вопросы
Можно ли на клиенте узнать логин Windows?
ПользовательОС у пользователя ИБ читается на сервере и заполнено, только если включена аутентификация операционной системы.Чем ТекущийПользователь отличается от АвторизованныйПользователь в БСП?
Сколько стоит вызов ИмяПользователя() в цикле?
Можно ли подменить текущего пользователя в коде?
Как узнать текущего пользователя в мобильном клиенте?
ИмяПользователя() на клиенте, ссылка на справочник — с сервера или из кэша БСП.