Данные текущего и любого пользователя из кода 1С: методы, права, примеры
Содержание
Чтобы программно получить профиль пользователя в 1С, на сервере вызовите ПользователиИнформационнойБазы.ТекущийПользователь(). Метод вернёт объект ПользовательИнформационнойБазы с именем, полным именем, уникальным идентификатором, ролями и способами входа. Для другого пользователя есть НайтиПоИмени() и НайтиПоУникальномуИдентификатору(), но им нужны административные права или привилегированный режим.
Это уровень платформы. В типовых конфигурациях (БП 3.0, ЗУП 3.1, УТ 11) поверх него лежит справочник Пользователи из БСП: там физлицо, подразделение, контакты. Полный профиль собирается из двух источников, и ниже показано, как связать их в одну структуру.
Что считать профилем: три уровня данных
Слово «профиль» в 1С расплывчатое. Сначала решите, что именно нужно, иначе код будет тянуть лишнее.
| Уровень | Где хранится | Что там есть | Чем получить |
|---|---|---|---|
| 🔑 Учётная запись | Список пользователей ИБ (платформа) | Имя, полное имя, UUID, роли, вход по паролю/ОС, язык, режим запуска | ПользователиИнформационнойБазы |
| 👤 Карточка | Справочник Пользователи (БСП) | Ссылка, физлицо, подразделение, контакты, признак «Недействителен» | Запрос, Пользователи.ТекущийПользователь() |
| 🖥 Сеанс | Память сервера | Номер сеанса, приложение, компьютер, время начала | ПолучитьТекущийСеансИнформационнойБазы() |
| ⚙️ Настройки | Хранилища настроек | Сохранённые формы, отборы, свои параметры | ХранилищеОбщихНастроек.Загрузить() |
Связь между первым и вторым уровнем — реквизит ИдентификаторПользователяИБ в справочнике. В нём лежит тот же UUID, что и у учётной записи.
Встроенные функции: быстрый способ получить пользователя 1С из кода
Для простых задач хватает глобальных функций. Они работают и на клиенте, и на сервере:
ИмяПользователя()— имя для входа, напримерБухгалтер1;ПолноеИмяПользователя()— полное имя, напримерИванова Мария Петровна;РольДоступна("ПолныеПрава")— есть ли у текущего пользователя роль;ПравоДоступа("Изменение", Метаданные.Справочники.Номенклатура)— есть ли право на объект.
Для полной учётной записи нужен серверный вызов. На тонком клиенте объект ПользователиИнформационнойБазы недоступен, поэтому делайте функцию &НаСервереБезКонтекста:
&НаСервереБезКонтекста
Функция ПрофильТекущегоПользователя()
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Профиль = Новый Структура;
Профиль.Вставить("Имя", ПользовательИБ.Имя);
Профиль.Вставить("ПолноеИмя", ПользовательИБ.ПолноеИмя);
Профиль.Вставить("УИД", Строка(ПользовательИБ.УникальныйИдентификатор));
Профиль.Вставить("ВходПоПаролю", ПользовательИБ.АутентификацияСтандартная);
Профиль.Вставить("ВходЧерезОС", ПользовательИБ.АутентификацияОС);
Профиль.Вставить("ПользовательОС", ПользовательИБ.ПользовательОС);
Роли = Новый Массив;
Для Каждого Роль Из ПользовательИБ.Роли Цикл
Роли.Добавить(Роль.Имя);
КонецЦикла;
Профиль.Вставить("Роли", Роли);
Возврат Профиль;
КонецФункции
Структура с простыми типами спокойно передаётся на клиент. Сам объект ПользовательИнформационнойБазы на клиент не передать — поэтому и нужна сборка в структуру.
Какие ещё свойства учётной записи пригодятся в профиле:
| Свойство | Тип | Что показывает |
|---|---|---|
ПарольУстановлен | Булево | Задан ли пароль (сам пароль не читается) |
ЗапрещеноИзменятьПароль | Булево | Может ли пользователь сменить пароль сам |
ПоказыватьВСпискеВыбора | Булево | Виден ли в списке при входе |
Язык | Объект метаданных | Язык интерфейса; пусто — язык по умолчанию |
РежимЗапуска | Перечисление | Обычное или управляемое приложение, авто |
ЗащитаОтОпасныхДействий | Объект | Включено ли предупреждение об опасных действиях |
АутентификацияOpenID | Булево | Разрешён ли вход через OpenID |
Если свойство пусто, это не ошибка. Например, пустой Язык значит, что берётся основной язык конфигурации. Для ФИО на экране используйте ПолноеИмя, а для поиска и логов — Имя: его пользователь вводит при входе, и оно уникально в пределах базы.
Если в базе нет ни одного пользователя, ТекущийПользователь() вернёт объект с пустым Имя. Проверяйте ПустаяСтрока(ПользовательИБ.Имя), если код должен отличать такую базу.
Справочник «Пользователи» и связь с учётной записью
В конфигурациях на БСП ссылку на текущего пользователя дают:
Пользователи.ТекущийПользователь()— ссылка на элемент справочникаПользователи;Пользователи.АвторизованныйПользователь()— то же, но может вернуть и внешнего пользователя;Пользователи.ЭтоПолноправныйПользователь()— Истина для администратора.
Разница между первыми двумя важна для порталов и личных кабинетов. Внешний пользователь — контрагент или физлицо, которому открыт доступ к части данных. Он лежит в справочнике ВнешниеПользователи, а не в Пользователи. Если в базе включены внешние пользователи, ТекущийПользователь() для такого входа вызовет исключение, а АвторизованныйПользователь() вернёт корректную ссылку. Тип результата проверяйте через ТипЗнч() перед чтением реквизитов.
Ссылка хранится в параметре сеанса, поэтому вызов дешёвый. Дальше реквизиты читаются запросом:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Пользователи.Наименование КАК Наименование,
| Пользователи.ФизическоеЛицо КАК ФизическоеЛицо,
| Пользователи.Подразделение КАК Подразделение,
| Пользователи.Недействителен КАК Недействителен,
| Пользователи.ИдентификаторПользователяИБ КАК ИдентификаторПользователяИБ
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Пользователи.ТекущийПользователь());
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ФизЛицо = Выборка.ФизическоеЛицо;
КонецЕсли;
Обратное направление — от учётной записи к карточке — делается по UUID:
УИД = ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор;
Ссылка = Справочники.Пользователи.НайтиПоРеквизиту("ИдентификаторПользователяИБ", УИД);
Для этого реквизита НайтиПоРеквизиту надёжен: UUID уникален, дублей быть не должно. Если вернулась пустая ссылка — учётная запись есть, а карточки нет. Так бывает после ручного создания пользователя в Конфигураторе.
Не ищите карточку по Наименование. Полные имена совпадают у однофамильцев и меняются при замужестве, а UUID постоянен.
Сеанс: кто, откуда и через какое приложение
Учётная запись не говорит, где человек сейчас работает. Это знает сеанс:
Сеанс = ПолучитьТекущийСеансИнформационнойБазы();
ДанныеСеанса = Новый Структура;
ДанныеСеанса.Вставить("НомерСеанса", Сеанс.НомерСеанса);
ДанныеСеанса.Вставить("Приложение", ПредставлениеПриложения(Сеанс.ИмяПриложения));
ДанныеСеанса.Вставить("Компьютер", Сеанс.ИмяКомпьютера);
ДанныеСеанса.Вставить("НачалоСеанса", Сеанс.НачалоСеанса);
ИмяПриложения возвращает служебную строку: ThinClient, WebClient, COMConnection, HTTPServiceConnection и т. п. Для показа пользователю оборачивайте её в ПредставлениеПриложения().
Что ещё полезно знать о сеансе:
- 🌐
ТекущийЯзык()— язык интерфейса сеанса; - 🗂
СтрокаСоединенияИнформационнойБазы()— файловая база или сервер, имя базы; - 📋
ПолучитьСеансыИнформационнойБазы()— все активные сеансы, у каждого есть свойствоПользователь; - 🔧
ПараметрыСеанса.<Имя>— значения, которые конфигурация заполняет при входе.
Параметры сеанса — частая находка при отладке. В БСП там лежит ТекущийПользователь, в отраслевых решениях — текущая организация или склад. Посмотреть список можно в Конфигураторе: ветка Общие → Параметры сеанса.
Пользовательские настройки тоже часть профиля. Свою настройку удобно хранить в общем хранилище:
// Сохранить
ХранилищеОбщихНастроек.Сохранить("МояОбработка", "ПоследнийСклад", Склад);
// Прочитать для текущего пользователя
Склад = ХранилищеОбщихНастроек.Загрузить("МояОбработка", "ПоследнийСклад");
Четвёртый параметр Загрузить() — имя пользователя. Чтение чужих настроек требует административных прав.
Профиль пользователя через HTTP-сервис и OData
Внешней системе (сайту, мобильному приложению, порталу) профиль удобно отдавать HTTP-сервисом. Платформа сама проверяет логин и пароль из заголовка Authorization. Внутри обработчика текущий пользователь — тот, кто прошёл аутентификацию.
Пошагово:
- В Конфигураторе добавьте HTTP-сервис, например
UserProfile, корневой URLprofile. - Создайте шаблон URL
/meи методGET. - В обработчике соберите данные и сериализуйте их в JSON.
- Опубликуйте базу на веб-сервере с публикацией HTTP-сервисов.
Функция MeGET(Запрос)
ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
Данные = Новый Структура;
Данные.Вставить("login", ПользовательИБ.Имя);
Данные.Вставить("fullName", ПользовательИБ.ПолноеИмя);
Данные.Вставить("id", Строка(ПользовательИБ.УникальныйИдентификатор));
Роли = Новый Массив;
Для Каждого Роль Из ПользовательИБ.Роли Цикл
Роли.Добавить(Роль.Имя);
КонецЦикла;
Данные.Вставить("roles", Роли);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Данные);
ТекстОтвета = ЗаписьJSON.Закрыть();
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(ТекстОтвета, КодировкаТекста.UTF8);
Возврат Ответ;
КонецФункции
Запрос с внешней стороны выглядит так (адрес и имя базы — свои):
curl -u "Бухгалтер1:пароль" "https://server/base/hs/profile/me"
ЗаписатьJSON сериализует структуры, массивы, строки, числа, булево и даты. Ссылки на справочники он не возьмёт — превращайте их в строку или UUID заранее.
Второй вариант — стандартный интерфейс OData. Без кода на стороне 1С можно читать справочник по адресу вида .../odata/standard.odata/Catalog_Пользователи?$format=json. Но сначала справочник нужно включить в состав интерфейса методом УстановитьСоставСтандартногоИнтерфейсаOData(). Учётные записи и роли через OData не отдаются — только данные справочника.
| Способ | Когда выбрать | Ограничения |
|---|---|---|
| HTTP-сервис | Нужен свой формат ответа, роли, проверки | Требует доработки конфигурации или расширения |
| OData | Достаточно реквизитов справочника | Нет данных учётной записи ИБ |
| COM/внешнее соединение | Скрипт на той же Windows-машине | Медленный старт, лицензия на соединение |
Для скрипта на той же машине подойдёт COM-соединение. В нём текущий пользователь — тот, чьи логин и пароль указаны в строке соединения:
Set Connector = CreateObject("V83.COMConnector")
Set Base = Connector.Connect("Srvr=""server"";Ref=""base"";Usr=""Бухгалтер1"";Pwd=""пароль"";")
WScript.Echo Base.ПолноеИмяПользователя()
Учтите, что каждое COM-соединение занимает сеанс и лицензию на время работы скрипта. Закрывайте его сразу, как получили данные.
HTTP-сервис можно добавить расширением конфигурации, не снимая типовую с поддержки.
Права доступа и обработка ошибок при чтении профиля
Свою учётную запись читает любой пользователь. Чужие — нет: НайтиПоИмени(), НайтиПоУникальномуИдентификатору() и ПолучитьПользователей() требуют права Администрирование. Без него платформа выбросит исключение о нехватке прав.
Есть два честных решения:
- Код в общем серверном модуле с
УстановитьПривилегированныйРежим(Истина)— только если модуль не принимает с клиента произвольное имя для поиска. - Чтение данных из справочника
Пользователи, где права уже настроены ролями конфигурации.
Безопасный шаблон поиска с проверками:
Функция СвойстваПользователяИБ(Идентификатор) Экспорт
УстановитьПривилегированныйРежим(Истина);
Попытка
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(Идентификатор);
Исключение
ЗаписьЖурналаРегистрации("Профиль пользователя",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Неопределено;
КонецПопытки;
Если ПользовательИБ = Неопределено Тогда
Возврат Неопределено; // учётную запись удалили
КонецЕсли;
Возврат Новый Структура("Имя, ПолноеИмя", ПользовательИБ.Имя, ПользовательИБ.ПолноеИмя);
КонецФункции
Не возвращайте на клиент пароль, хеш пароля и полный список ролей другого пользователя. Привилегированный режим снимает все ограничения, поэтому решение о том, что отдать, принимает код.
Частые сбои и что за ними стоит:
Массовое получение профилей без тормозов
Отчёт «все пользователи с ролями» или выгрузка в кадровый портал легко превращается в медленный цикл. Типичная ошибка — вызывать НайтиПоУникальномуИдентификатору() для каждой строки справочника.
Как делать быстрее:
- Один раз вызовите
ПользователиИнформационнойБазы.ПолучитьПользователей(). - Разложите результат в
Соответствиес ключом UUID. - Одним запросом прочитайте справочник
Пользователи. - Сопоставляйте записи по
ИдентификаторПользователяИБчерез соответствие.
УстановитьПривилегированныйРежим(Истина);
УчётныеЗаписи = Новый Соответствие;
Для Каждого ПользовательИБ Из ПользователиИнформационнойБазы.ПолучитьПользователей() Цикл
УчётныеЗаписи.Вставить(ПользовательИБ.УникальныйИдентификатор, ПользовательИБ);
КонецЦикла;
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Пользователи.Ссылка КАК Ссылка,
| Пользователи.ИдентификаторПользователяИБ КАК УИД
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| НЕ Пользователи.ПометкаУдаления");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ПользовательИБ = УчётныеЗаписи.Получить(Выборка.УИД);
Если ПользовательИБ = Неопределено Тогда
Продолжить; // карточка без учётной записи
КонецЕсли;
// работа с Выборка.Ссылка и ПользовательИБ
КонецЦикла;
Для 300 пользователей это один проход по списку и один запрос вместо 300 отдельных поисков.
Ещё три приёма:
- 🧠 Профиль текущего пользователя, который нужен в каждой форме, кешируйте в общем модуле с повторным использованием возвращаемых значений «На время сеанса».
- 📦 Из справочника берите только нужные поля, а не
Выборка.Ссылка.ФизическоеЛицочерез точку: каждое разыменование — лишнее обращение к базе. - ⏱ Роли перебирайте, только если они реально нужны. Для проверки одной роли у текущего пользователя хватает
РольДоступна().
Кешированный профиль не обновится, пока сеанс жив. Если администратор поменял роли, изменения увидит только новый сеанс.
Частые вопросы
Можно ли узнать пароль пользователя программно?
ПарольУстановлен. Пароль можно задать новым значением, но прочитать нельзя.