Как определить пользователя в процедуре ПередНачаломРаботыСистемы()?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке на платформе «1С:Предприятие 8» (особенно под управляемый интерфейс) часто возникает задача выполнить определенные действия при самом старте системы. Например, нам может потребоваться проверить права пользователя, установить для него специализированные настройки интерфейса, заблокировать вход определенной группе лиц или запустить систему в режиме киоска. Традиционно для этих целей используется предопределенная процедура ПередНачаломРаботыСистемы(), расположенная в модуле управляемого приложения.

Однако на этом этапе разработчики часто сталкиваются со следующей проблемой: привычные методы получения текущего пользователя либо вызывают ошибки компиляции, либо возвращают пустые значения. В этой статье мы подробно разберем, как устроен жизненный цикл запуска системы 1С, почему возникают сложности с контекстом исполнения и какими способами можно гарантированно и правильно определить пользователя в процедуре ПередНачаломРаботыСистемы().

Порядок запуска системы и развенчание мифов о параметрах сеанса

Среди разработчиков 1С существует распространенное заблуждение, будто в момент вызова процедуры ПередНачаломРаботыСистемы() параметры сеанса еще не инициализированы платформой, и именно поэтому к ним нельзя обратиться. Давайте разберем реальный порядок инициализации и запуска клиентского приложения:

  1. Инициализация сеанса на сервере: Сначала платформа создает сеанс на сервере и запускает Модуль сеанса. В нем отрабатывает событие УстановкаПараметровСеанса (с параметром Неопределено в качестве массива имен).
  2. Загрузка клиента: Управление передается на клиентскую сторону в Модуль управляемого приложения.
  3. Выполнение тела модуля: Выполняются инструкции, написанные непосредственно в тексте модуля управляемого приложения вне процедур и функций (если они там есть).
  4. Событие ПередНачаломРаботыСистемы(): Платформа вызывает процедуру ПередНачаломРаботыСистемы() на клиенте.
  5. Событие ПриНачалеРаботыСистемы(): Если предыдущий шаг прошел успешно и параметр Отказ не был установлен в значение Истина, вызывается процедура ПриНачалеРаботыСистемы().

Таким образом, параметры сеанса на сервере уже давно инициализированы к моменту начала работы клиента! Настоящая причина проблемы кроется исключительно в контексте исполнения. Процедура ПередНачаломРаботыСистемы() выполняется строго на клиенте (в тонком, толстом или веб-клиенте). Объект ПараметрыСеанса физически недоступен на клиенте в тонком и веб-клиентах, попытка прямого обращения к нему вызовет ошибку компиляции кода. Чтобы получить параметры сеанса, нам необходимо совершить явный переход с клиента на сервер.

Вариант 1. Использование функции ИмяПользователя()

Самый простой и быстрый способ узнать, кто запускает систему, — использовать стандартную глобальную функцию встроенного языка ИмяПользователя(). Она доступна непосредственно на клиенте, поэтому ее можно вызывать без каких-либо дополнительных серверных вызовов.

Рассмотрим пример использования:


Процедура ПередНачаломРаботыСистемы(Отказ)
    
    ТекущееИмя = ИмяПользователя();
    Если СокрЛП(ТекущееИмя) = "Администратор" Тогда
        // Выполняем действия для администратора
    КонецЕсли;
    
КонецПроцедуры

Важные нюансы и ограничения:

Несмотря на простоту, у этого метода есть существенные недостатки:

Вариант 2. Получение пользователя ИБ через серверный вызов

Если нам необходимо получить полную информацию о пользователе информационной базы (его уникальный идентификатор, настройки, имя для входа) или безопасно обратиться к параметрам сеанса, мы должны использовать серверный вызов.

Для этого создадим общий модуль с установленными свойствами «Сервер» и «Вызов сервера» (например, с именем РаботаСПользователямиСервер). Реализуем в нем следующую функцию:


Функция ПолучитьДанныеТекущегоПользователя() Экспорт
    
    Результат = Новый Структура;
    Результат.Вставить("Имя", "");
    Результат.Вставить("УникальныйИдентификатор", Неопределено);
    
    ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если ТекущийПользовательИБ <> Неопределено Тогда
        Результат.Имя = ТекущийПользовательИБ.Имя;
        Результат.УникальныйИдентификатор = ТекущийПользовательИБ.УникальныйИдентификатор;
    КонецЕсли;
    
    Возврат Результат;
    
КонецФункции

Теперь мы можем легко и безопасно вызвать эту функцию на клиенте в модуле управляемого приложения:


Процедура ПередНачаломРаботыСистемы(Отказ)
    
    ДанныеПользователя = РаботаСПользователямиСервер.ПолучитьДанныеТекущегоПользователя();
    
    ИмяИБ = ДанныеПользователя.Имя;
    УИД   = ДанныеПользователя.УникальныйИдентификатор;
    
    // Пример поиска пользователя в справочнике "Пользователи" по УИД
    СсылкаНаПользователя = РаботаСПользователямиСервер.НайтиПользователяПоУИД(УИД);
    
КонецПроцедуры

Этот подход полностью решает проблему работы в веб-клиенте, поскольку на стороне сервера платформа гарантированно обладает всей информацией о текущем сеансе и авторизованном пользователе.

Вариант 3. Использование Библиотеки стандартных подсистем (БСП)

Если ваша конфигурация разработана на основе Библиотеки стандартных подсистем (БСП), вам не нужно писать собственные велосипеды для связи пользователей информационной базы со справочником Пользователи. В БСП для этого предусмотрены готовые механизмы.

Для определения текущего авторизованного пользователя (который является элементом справочника Пользователи) мы можем использовать функцию общего модуля ПользователиКлиентСервер.АвторизованныйПользователь(). Проанализируем, как устроен этот механизм изнутри:


Функция ТекущийПользователь() Экспорт
    
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
    Возврат Пользователи.ТекущийПользователь();
#Иначе
    Возврат ПользователиКлиент.ТекущийПользователь();
#КонецЕсли
    
КонецФункции

Важное предостережение при работе с БСП:

В БСП активно применяется кэширование данных на клиенте для оптимизации производительности. В момент выполнения процедуры ПередНачаломРаботыСистемы() клиентский кэш БСП может быть еще не инициализирован до конца. Поэтому попытка получить пользователя напрямую через ПользователиКлиент.ТекущийПользователь() может вернуть пустую ссылку или вызвать ошибку инициализации параметров сеанса.

Для надежного обхода этой проблемы рекомендуется принудительно запрашивать авторизованного пользователя через серверную функцию БСП:


Процедура ПередНачаломРаботыСистемы(Отказ)
    
    // Надежное получение ссылки на элемент справочника "Пользователи" через БСП
    ТекущийПользовательСправочник = ОбщегоНазначенияВызовСервера.ИндексВызова(
        "Пользователи.АвторизованныйПользователь"
    );
    
    // Либо прямой вызов серверной функции БСП, если это допустимо в вашей версии
    ТекущийПользовательСправочник = Пользователи.АвторизованныйПользователь();
    
КонецПроцедуры

Проверка ролей и прав доступа

Зачастую определение пользователя в процедуре ПередНачаломРаботыСистемы() требуется лишь для того, чтобы проверить его права (например, разрешено ли ему запускать программу или выполнять административные функции).

Обратите внимание, что на момент выполнения этого события роли пользователя уже полностью прочитаны платформой и активны. Вы можете проверять доступность ролей непосредственно на клиенте без переходов на сервер с помощью стандартной функции РольДоступна():


Процедура ПередНачаломРаботыСистемы(Отказ)
    
    // Проверка роли непосредственно на клиенте без обращения к серверу
    Если Не РольДоступна("ПолныеПрава") И Не РольДоступна("ИнтерфейсКассира") Тогда
        Предупреждение("У вас нет прав на запуск данного рабочего места!");
        Отказ = Истина;
    КонецЕсли;
    
КонецПроцедуры

Тем не менее, если вам требуется проверить сложные ограничения (например, доступ по RLS или дополнительные настройки из справочников), рекомендуется переносить логику проверки на сторону сервера, передавая на клиент лишь итоговый вердикт (разрешить запуск или нет).

Резюме и рекомендации

Подводя итоги, выделим лучшие практики для определения пользователя при старте системы:

  1. Используйте ИмяПользователя() только для простейших отладочных сценариев или в базах, где гарантированно не будет использоваться веб-клиент и доменная авторизация.
  2. Для надежной работы в любых средах (включая веб-клиент) запрашивайте данные пользователя через серверный вызов функции общего модуля.
  3. В конфигурациях на базе БСП отдавайте предпочтение функции Пользователи.АвторизованныйПользователь(), вызываемой в серверном контексте, чтобы получить ссылку на справочник пользователей с учетом всех установленных прав и замещений.
  4. Если целью определения пользователя является проверка его прав, по возможности используйте быструю клиентскую функцию РольДоступна(), чтобы минимизировать нагрузку на сервер при запуске приложения.
← На главную