Как мигрировать хеш пароля
Дата обновления перевода 2023-07-24
Как мигрировать хеш пароля
Для того, чтобы защищать пароли, рекомендуется хранить их, используя последние
алгоритмы хеширования. Это означает, что если в вашей системе поддерживается лучший
алгоритм хеширования, пароль польозвателя должен быть хеширован повторно, используя
более новый алгоритм, и сохранен. Это возможно с опцией migrate_from
:
- Сконфигурируйте новый хешировщик, используя "migrate_from"
- Обновите пароль
- По желанию, Запустите миграцию паролей из пользовательского хешировщика
Сконфигурируйте новый хешировщик, используя "migrate_from"
Когда становится доступным лучший алгоритм хеширования, вы должны оставить существующий(е)
хешировщик(и), переименовать его, а затем определить новый. Установите опцию migrate_from
в новом хещировщике, чтобы указать на старый, наследуемый(е) хешироващик(и):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# config/packages/security.yaml
security:
# ...
password_hashers:
# хешировщик, используемый в прошлом для некоторых пользователей
legacy:
algorithm: sha256
encode_as_base64: false
iterations: 1
App\Entity\User:
# новый хешироващик, вместе с его опциями
algorithm: sodium
migrate_from:
- bcrypt # использует хешировщик "bcrypt" с опциями по умолчанию
- legacy # использует хешировщик "legacy", сконфигурированный выше
С этой настройкой:
- Новые пользователи будут хешироваться с новым алгоритмом;
- Каждый раз при входе в систему пользователя, чей пароль все еще хранится с использованием старого алгоритма, Symfony будет верифицировать пароль со старым алгоритмом, а затем повторно хешировать и обновлять пароль, используя новый алгоритм.
Tip
Хешировщики auto, native, bcrypt и argon автоматически включают
миграцию паролей, используя следующий список алгоритмов migrate_from
:
- PBKDF2 (который использует hash_pbkdf2);
- Хеш (который использует hash)
Оба используют настройку hash_algorithm
в качестве алгоритма. Рекомендуется
использовать migrate_from
вместо hash_algorithm
, кроме случаев использования
хешировщика auto.
Обновите пароль
После успешного входа в систему, система Безопасности проверяет, доступен ли лучший алгоритм для хеширования пароля пользователя. Если доступен, то она хеширует правильный пароль, используя новый хеш. Если вы используете аутентификатор Guard, сначала вам нужно предоставить изначальный пароль системе Безопасности.
Вы можете подключить поведение обновления, реализовав, как этот новохешированный пароль должен быть сохранен:
- При использовании сущности поставщика пользователей Doctrine
- При использовании пользовательского поставщика пользователей
После этого, вы закончили, и пароли всегда будут хешированы максимально безопасно!
Предоставьте пароль при использовании Guard
Когда вы использоуете пользовательский аутентификатор guard,
вам нужно реализовать PasswordAuthenticatedInterface.
Этот интерфейс определяет метод getPassword()
, который возвращает пароль для этого запроса входа
в систему. Этот пароль используется в процессе миграции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// src/Security/CustomAuthenticator.php
namespace App\Security;
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface;
// ...
class CustomAuthenticator extends AbstractGuardAuthenticator implements PasswordAuthenticatedInterface
{
// ...
public function getPassword($credentials): ?string
{
return $credentials['password'];
}
}
Обновите пароль при использовании Doctrine
При использовании сущности поставщика пользователей,
реализуйте PasswordUpgraderInterface в
UserRepository
(см. документацию Doctrine, чтобы получить информацию о том, как
создать этот класс, если он еще не создан). Этот интерфейс реализует хранение новосозданного
хеша паролей:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// src/Repository/UserRepository.php
namespace App\Repository;
// ...
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
class UserRepository extends EntityRepository implements PasswordUpgraderInterface
{
// ...
public function upgradePassword(UserInterface $user, string $newHashedPassword): void
{
// установите новохешированный пароль в объекте User
$user->setPassword($newHashedPassword);
// выполните запросы в БД
$this->getEntityManager()->flush();
}
}
Обновите пароль при использовании пользовательского поставщика пользователей
Если вы используете пользовательского поставщика пользователей, реализуйте PasswordUpgraderInterface в поставщике пользователей:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// src/Security/UserProvider.php
namespace App\Security;
// ...
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
class UserProvider implements UserProviderInterface, PasswordUpgraderInterface
{
// ...
public function upgradePassword(UserInterface $user, string $newHashedPassword): void
{
// установите новохешированный пароль в объекте User
$user->setPassword($newHashedPassword);
// ... сохраните новый пароль
}
}
Запустите миграцию паролей из пользовательского хешировщика
Если вы используете пользовательский хешировщик паролей, вы можете вызвать
миграцию паролей, вернув true
в методе needsRehash()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// src/Security/CustomPasswordHasher.php
namespace App\Security;
// ...
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
class CustomPasswordHasher implements UserPasswordHasherInterface
{
// ...
public function needsRehash(string $hashed): bool
{
// проверить, хешируется ли текущий пароль с использованием устаревшего хешировщика
$hashIsOutdated = ...;
return $hashIsOutdated;
}
}