Америку открывать никому не собираюсь, но как это ни странно, после получаса блуждания по просторам интернета я так и не нашёл конкретного описания, как можно сравнить введённый пароль с паролем текущего пользователя без его модификации (как это, например, реализовано в публикации 102655).
На деле всё оказалось довольно просто. В справке к свойству СохраняемоеЗначениеПароля объекта типа ПользовательИнформационнойБазы написано:
Содержит хранимые значения пароля (хеш-функции) и хранимые значения пароля в верхнем регистре (хеш-функции) разделенные запятой.
Только не указано, какие конкретно для этого используются хэш-функции. Для значения пароля «Привет» свойство содержит строку «KAWujn4S8YITX5L7kIQ7sQgNO+g=,c9a04UjoS/W0iLeU7GUa9/Ltd1E=».
Немного покопавшись в «сети», можно найти такую формулировку «sha-1, обёрнутый в base64». Складывая всё вместе, выводим следующий алгоритм:
Функция ПолучитьХешПароля(Пароль) Экспорт
Хеш = Новый ХешированиеДанных(ХешФункция.SHA1);
Хеш.Добавить(Пароль);
Возврат Base64Строка(Хеш.ХешСумма);
КонецФункции
Проверяем на нашем пароле «Привет» и убеждаемся, что получившееся значение действительно совпадает с левой частью из сохраненного хеша.
Дальше с помощью функции получаем текущее значение свойства СохраняемоеЗначениеПароля, не забывая установить привилегированный режим (т.к. «доступно только пользователю с административными правами»), декомпозируем его на регистрозависимую (слева от запятой) и регистронезависимую (справа) части и сравниваем полученные значения.
Функция ПроверитьТекущийПарольПользователя(Пароль, РегистроНезависимый=Истина) Экспорт
УстановитьПривилегированныйРежим(Истина);
ХешТекущегоПароля = ПользователиИнформационнойБазы.ТекущийПользователь().СохраняемоеЗначениеПароля;
УстановитьПривилегированныйРежим(Ложь);
Если ХешТекущегоПароля = Пароль Тогда Возврат Истина КонецЕсли; // Пароль совпадает с СохраняемоеЗначениеПароля только в случае пустого значения
ПозицияРазделителя = Найти(ХешТекущегоПароля, ",");
Результат = Ложь;
Если РегистроНезависимый Тогда
Результат = ПолучитьХешПароля(ВРег(Пароль)) = Прав(ХешТекущегоПароля, СтрДлина(ХешТекущегоПароля) - ПозицияРазделителя);
Иначе
Результат = ПолучитьХешПароля(Пароль) = Лев(ХешТекущегоПароля, ПозицияРазделителя - 1);
КонецЕсли;
Возврат Результат;
КонецФункции
Вуаля! Ну, и на последок приведу еще функцию, формирующую значение свойства СохраняемоеЗначениеПароля из введенного пароля.
Функция ПолучитьСохраняемоеЗначение(Пароль) Экспорт
Возврат ?(ЗначениеЗаполнено(Пароль),ПолучитьХешПароля(Пароль) + "," + ПолучитьХешПароля(ВРег(Пароль),"");
КонецФункции
Благодарю за статью, пригодилась.
Как-то у вас получилось одевание штанов через голову. Не проще ли программно получать сохраняемое значение пароля и сравнивать его с хранимым в базе?
Не учитывается незаполненный пароль, для него сохраняемое значение пароля равно «».
Для себя когда-то сделал обработку (см. вложение).
Также в БП что-то похожее есть в модуле
ЭлектроннаяПодписьВМоделиСервисаСлужебный
Меня смущает что 1С не использует при хэшировании «соль»(разную для каждого пользователя или хотя бы единую на всю базу). В этом случае восстановить(подобрать) пароли пользователей становится гораздо проще.
(2) bonv, за конструктивную критику о проверке на пустое значение благодарствую, в код добавил коррективы.
А вот про «одевание штанов через голову» давайте разберём, у кого же оно получилось «через голову».
Во-первых, откуда брать значение текущего пароля (из БД или из сеанса) — это исключительно зависит от подхода разработчика. Например, в НФ при смене пароля (меню Сервис — Параметры пользователя) разработчики платформы проверяют введённый пароль сеанса, т.е. из ПользователиИнформационнойБазы.ТекущийПользователь() (проверено эмпирически), разработчики БСП в приведённом Вами примере проверяют значение из БД, т.к. в функцию пользователь передается параметром.
Во-вторых, я совершенно не понял фразы «не проще ли программно получать сохраняемое значение пароля». А я его аппаратно что-ли получаю?
В-третьих, небольшой совет на будущее: прежде чем добавлять в свои сообщения едкий сарказм стоит получше вникнуть в комментируемый текст, дабы потом не было стыдно за сказанное. В статье приведён пример функции, которая в зависимости от передаваемого 2-го параметра сравнивает пароль в зависимой от регистра форме и в независимой. В какой форме проверять — остается на выбор использующего. В Вашей же обработке (как впрочем и в функции БСП) сравнение идёт только в регистрозависимом режиме, т.к. проверяются одновременно оба хранимых хэша.
Ну, и в-четвёртых, почему я не стал оборачивать этот код в обработку, а написал в статье? Потому что если внимательно почитать справку, а потом ещё внимательно почитать мою статью, для получения значения СохраняемоеЗначениеПароля необходимы административные права, а соответственно большинство пользователей использовать эту функцию через обработку не смогут, а установка привилегированного режима во внешней обработке бессмысленна. Соответственно делать это нужно во внутренних механизмах конфигурации, идеально для этого подходят общие формы. Поэтому публикация оформлена в виде статьи, а не обработки (как в Вашем случае).
(3) rtnm, меня много чего смущает в продуктах 1С… но преимущества пока перевешивают… ))
(4)
1. В моем комментарии не было замечания по этому пункту
2.
действительно не поняли
3. Да, действительно, погорячился. Я был не прав, т.к. в моем случае всегда установлена проверка сложности паролей и соответственно используется регистрозависимая проверка. И для моих целей этого достаточно.
4. О какой публикации речь? Я приложил обработку (ее я сделал задолго до Вашей публикации с целью отладки своей функции), чтобы проиллюстрировать свой комментарий.
(6) bonv,
было
хоть, похоже, и не умышленно…
т.е. пояснений не будет?
к слову сказать, по умолчанию при штатной аутентификации 1С на входе проверка пароля производится без учета регистра (для этого-то в СохраняемоеЗначениеПароля и присутствует хэш пароля в верхнем регистре), но при установке в настройках ИБ (меню Администрирование — Параметры информационной базы…) галочки Проверка сложности паролей пользователей она будет производиться уже по регистрозависимой форме. Поэтому при вызове моего варианта это довольно легко реализовать при передаче в функцию вторым параметром выражения НЕ ПолучитьПроверкуСложностиПаролейПользователей(), а в Вашем случае пользователь может в систему войти, а при проверке получить ошибку и долго удивляться.
о моей, которую Вы и комментируете…
А кто нибуть разбирался как формируется запись пароля подключения к СУБД в файле srvribrg.lst
По идеи механизм формирования должен быть похож.
Пример из файла:
{6fe8ec41-e16b-422b-9073-cb214248591a,»Torg»,»»,»PostgreSQL»,»dell2900″,»torgovlya»,»postgres»,»X4zp8HCS6WwSInfaP1n6vX+DnyVU0Hj6RwkD8poAcCE=»,»CrSQLDB=Y;DB=torg;DBMS=PostgreSQL;DBSrvr=dell2900;DBUID=postgres;Locale=ru_RU;Ref=torg;SLev=0;Srvr=dell2900;SUsr=»,0,
{0,00010101000000,00010101000000,»»,»»,»»},0},
(8) Bad_Developer,
нет, не должен. Потому что здесь пароль шифруется, а не хэшируется. Разница между между этими понятиями проста: в первом случае исходный пароль можно восстановить (дешифровать) обратным алгоритмом, в то время как получение хэша во втором случае — это односторонний процесс и единственный способ выхода на исходный пароль — это «брутфорс» со сравнением результата шифрования.
Это ж до меня тут дошло неожиданно, что если первый и второй хеши совпадают, то это с высоченной долей вероятности говорит о том, что пароль цифровой. Вот дырень-то…
(10) baton_pk, ну допустим «дырень» не в платформе 1С, а в голове администратора системы, т.к. в параметрах информационной базы есть настройка «Проверка сложности паролей пользователей», при установке которой система не допустит использования «цифрового пароля».
(11)
позволю себе не согласиться 🙂 мы админим магазины через DameWare и чтобы избежать головной боли с разницей раскладок на локальном компе и на удалённом компе, используем длинный цифровой пароль для админа.
(12) baton_pk, я не совсем понял, с чем же высказано несогласие?
перевожу «мы в угоду удобству отказались от общепринятых рекомендаций по формированию политике безопасности, но стараемся компенсировать это длиной пароля».
Ну, да ладно, спор о том, у кого длиннее цифровой пароль, здесь немного неуместен.
Только вопрос «дырени», как я его понял, относился к проверке установки паролей пользователями, а не админами. Какой смысл админу в системе самому себе заводить ограничения?
(13)
Поясню. Пароли мы админим из главного узла — они выгружаются в XML-ку. Соответственно, знающий человек может разобрать XML-ку, выдрать отттуда сохраняемое значение пароля и проанализировать его.
Хотя это из разряда фантастики всё-таки…
(10) baton_pk,
ИЛИ ВСЕ КАПСОМ НАБРАНО)