Как повторно запросить пароль пользователя для доступа к закрытым данным в 1С 8.3?

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

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

Разберем, почему нельзя просто вызвать стандартное системное окно входа 1С посреди сеанса, и подробно рассмотрим доступные технические решения для безопасной проверки пароля.

Вариант 1. Сверка пароля через создание временного пользователя (метод БСП)

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

Рассмотрим, как работает данный алгоритм на клиенте и сервере. На клиенте мы запрашиваем строку с маской пароля, а на сервере выполняем проверку:


&НаКлиенте
Процедура ПриПереходеНаЗакладкуОклад(Команда)
    ПараметрыВвода = Новый ПараметрыДиалогаВводаДанных;
    ПараметрыВвода.Подсказка = "Введите пароль вашей учетной записи 1С:";
    ПараметрыВвода.Маска = Истина;
    
    Оповещение = Новый ОписаниеОповещения("ПослеВводаПароля", ЭтотОбъект);
    ПоказатьВводТекста(Оповещение, "", "Подтверждение доступа", ПараметрыВвода);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВводаПароля(ВведенныйПароль, ДополнительныеПараметры) Экспорт
    Если ВведенныйПароль = Неопределено Тогда
        // Пользователь отменил ввод
        Возврат;
    КонецЕсли;
    
    Если ПроверитьПарольТекущегоПользователя(ВведенныйПароль) Тогда
        // Пароль верный — открываем страницу
        Элементы.ГруппаСтраницы.ТекущаяСтраница = Элементы.СтраницаОклад;
    Иначе
        ПоказатьПредупреждение(, "Введен неверный пароль. Доступ ограничен.");
    КонецЕсли;
КонецПроцедуры

На сервере в привилегированном режиме выполняем создание временного пользователя, считываем сформированный платформой хэш и сразу удаляем временный объект:


&НаСервереБезКонтекста
Функция ПроверитьПарольТекущегоПользователя(ВведенныйПароль)
    УстановитьПривилегированныйРежим(Истина);
    
    ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если ТекущийПользовательИБ = Неопределено Тогда
        Возврат Ложь;
    КонецЕсли;
    
    // Создаем временного пользователя для генерации хэша
    ВременныйПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
    ВременныйПользовательИБ.АутентификацияСтандартная = Ложь;
    ВременныйПользовательИБ.Пароль = ВведенныйПароль;
    ВременныйПользовательИБ.Имя = "TempAuthCheck_" + Строка(Новый УникальныйИдентификатор);
    ВременныйПользовательИБ.Записать();
    
    // Считываем сформированное платформой сохраняемое значение
    ВременныйПользовательИБ = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(
        ВременныйПользовательИБ.УникальныйИдентификатор
    );
    ХэшВведенногоПароля = ВременныйПользовательИБ.СохраняемоеЗначениеПароля;
    
    // Удаляем временного пользователя
    ВременныйПользовательИБ.Удалить();
    
    // Сравниваем со значением текущего пользователя
    Возврат (ХэшВведенногоПароля = ТекущийПользовательИБ.СохраняемоеЗначениеПароля);
КонецФункции

Вариант 2. Проверка пароля через отмену транзакции

Чтобы не создавать и не удалять новых пользователей в служебных таблицах, разберем альтернативный вариант — применение транзакции к объекту текущего пользователя с последующей ее отменой:

  1. Запоминаем исходное свойство СохраняемоеЗначениеПароля текущего пользователя.
  2. Открываем транзакцию вызовом НачатьТранзакцию().
  3. Присваиваем свойству Пароль введенный пользователем текст и вызываем Записать().
  4. Считываем новое СохраняемоеЗначениеПароля.
  5. Обязательно вызываем ОтменитьТранзакцию(), чтобы изменения пароля не сохранились в базе.
  6. Сравниваем исходное и полученное внутри транзакции значения.

&НаСервереБезКонтекста
Функция ПроверитьПарольЧерезТранзакцию(ВведенныйПароль)
    УстановитьПривилегированныйРежим(Истина);
    
    ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если ПользовательИБ = Неопределено Тогда
        Возврат Ложь;
    КонецЕсли;
    
    ИсходныйХэш = ПользовательИБ.СохраняемоеЗначениеПароля;
    
    НачатьТранзакцию();
    Попытка
        ПользовательИБ.Пароль = ВведенныйПароль;
        ПользовательИБ.Записать();
        
        // Считываем обновленный объект
        ПроверяемыйПользователь = ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(ПользовательИБ.УникальныйИдентификатор);
        НовыйХэш = ПроверяемыйПользователь.СохраняемоеЗначениеПароля;
        
        ОтменитьТранзакцию();
        Возврат (ИсходныйХэш = НовыйХэш);
    Исключение
        ОтменитьТранзакцию();
        ВызватьИсключение;
    КонецПопытки;
КонецФункции

Вариант 3. Прямое вычисление SHA-1 хэша средствами 1С

Платформа 1С формирует СохраняемоеЗначениеПароля по определенному стандарту: строка содержит два хэша SHA-1 в кодировке Base64, разделенных запятой. Первый хэш считается от строки с сохранением регистра, второй — от строки в верхнем регистре (ВРег).

Посмотрим на программную реализацию расчета хэша без записи пользователя:


&НаСервереБезКонтекста
Функция ПолучитьХэшПароля1С(Пароль)
    ХешированиеРегистр = Новый ХешированиеДанных(ХешФункция.SHA1);
    ХешированиеРегистр.Добавить(Пароль);
    Хэш1 = Base64Строка(ХешированиеРегистр.ХешСумма);
    
    ХешированиеВерхний = Новый ХешированиеДанных(ХешФункция.SHA1);
    ХешированиеВерхний.Добавить(ВРег(Пароль));
    Хэш2 = Base64Строка(ХешированиеВерхний.ХешСумма);
    
    Возврат Хэш1 + "," + Хэш2;
КонецФункции

&НаСервереБезКонтекста
Функция ПроверитьПарольРасчетомХэша(ВведенныйПароль)
    УстановитьПривилегированныйРежим(Истина);
    
    ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если ПользовательИБ = Неопределено Тогда
        Возврат Ложь;
    КонецЕсли;
    
    ВычисленныйХэш = ПолучитьХэшПароля1С(ВведенныйПароль);
    Возврат (ВычисленныйХэш = ПользовательИБ.СохраняемоеЗначениеПароля);
КонецФункции

Вариант 4. Штатная блокировка сеанса через ЗаблокироватьРаботуПользователя()

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

Важные ограничения и нюансы реализации

  1. Привилегированный режим: Чтение свойства СохраняемоеЗначениеПароля и работа с коллекцией ПользователиИнформационнойБазы требуют полных административных прав. Чтобы обычные менеджеры не получали ошибку нарушения прав доступа, проверку необходимо выполнять в привилегированном модуле или внутри конструкции УстановитьПривилегированныйРежим(Истина).
  2. Доменная авторизация и OpenID: Если в компании настроена сквозная аутентификация операционной системы (Active Directory) или SSO, у пользователя может быть отключена стандартная аутентификация 1С (АутентификацияСтандартная = Ложь). В этом случае свойство СохраняемоеЗначениеПароля будет пустым.
  3. Альтернатива с отдельным PIN-кодом: Для закрытых внутренних панелей и отчетов практичнее завести отдельный короткий PIN-код доступа (из 4–6 цифр) для каждого сотрудника и хранить его хэш в регистре сведений. Это избавляет от проблем с доменной авторизацией и делает ввод подтверждения более удобным для пользователей.
← На главную