В большинстве систем управления сайтом такой функционал идет "из коробки". Не знаю, почему многоуважаемые творцы битрикса до сих пор не реализовали данный функционал в типовых механизмах, однако, очень часто может быть необходимо выполнять какие-то действия только при подтверждении действий текущим паролем (например, нужно изменить логин/пароль в личном кабинете). Для этого может пригодиться следующий алгоритм ...
Рассмотрим алгоритм на примере изменения пароля. Пусть пост-запросом в наш обработчик пришли параметры: PASSWORD - введенный пользователем текущий пароль, NEW_PASSWORD - введенный пользователем новый пароль и CONFIRM_NEW_PASSWORD - подтверждение нового пароля пользователя. Тогда, получам алгоритма:
$arUser["PASSWORD"] = $USER->GetParam("PASSWORD_HASH");
$arParams["PASSWORD"] = $_POST['PASSWORD'];
$arParams["NEW_PASSWORD"] = $_POST['NEW_PASSWORD'];
$arParams["NEW_PASSWORD_CONFIRM"] = $_POST['CONFIRM_NEW_PASSWORD'];
if (strlen($arUser["PASSWORD"]) > 32) {
$salt = substr($arUser["PASSWORD"], 0, strlen($arUser["PASSWORD"]) - 32);
$db_password = substr($arUser["PASSWORD"], -32);
} else {
$salt = "";
$db_password = $arUser["PASSWORD"];
}
$user_password = md5($salt . $arParams["PASSWORD"]);
if ($user_password == $db_password || $arParams["NEW_PASSWORD"] !== $arParams["NEW_PASSWORD_CONFIRM"]){
$user = new CUser;
$fields = Array(
"PASSWORD" => $arParams["NEW_PASSWORD"],
"CONFIRM_PASSWORD" => $arParams["NEW_PASSWORD_CONFIRM"],
);
$user->Update($USER->GetID(), $fields);
if (strlen($user->LAST_ERROR) > 0) {
ShowError($user->LAST_ERROR);
} else {
ShowNote('Пароль изменен');
} ?>
}else{
ShowError('Не верный текущий пароль');
}
Сначала получаем хещ пароля текущего пользователя. Далее отделяем от хеша пароля добавленную "соль". Потом шифруем введенный пользователем пароль вместе с добавленной к нему солью и сверяем полученный хеш с тем, что хранится в базе.
Если пароли сходятся - пробуем обновить пароль, если же нет - выводим соответствующее предупреждение.
Update 2024-10-23
Чтобы получить хеш-пароля в формате ядра D7 можно воспользоваться такой конструкцией:
$q = new \Bitrix\Main\ORM\Query\Query(\Bitrix\Main\UserTable::getEntity());
$q->enablePrivateFields();
$q->setSelect([
'ID' => 'ID',
'LOGIN' => 'LOGIN',
'PASSWORD' => 'PASSWORD',
]);
$q->setFilter([
'=ID' => \Bitrix\Main\Engine\CurrentUser::get()->getId(),
]);
$result = $q->fetch();
