Перенос паролей из легаси PHP приложения в Laravel
Это происходит из-за того, что драйвер хэширования Laravel по умолчанию — bcrypt и использует argon в качестве ещё одной встроенной опции, в то время, как MD5, SHA-1, SHA-256 и SHA-512 до сих пор широко используются, особенно если приложение построено не на современном фреймворке.
Учитывая, что у нас уже есть таблица, в которой хранятся хэшированные пароли, нам нужно заставить Laravel использовать правильный алгоритм хэширования для сравнения необработанных паролей при аутентификации.
Создание драйвера хэширования для Laravel
Он должен реализовать интерфейс Illuminate\Contracts\Hashing\Hasher и расширить класс Illuminate\Hashing\AbstractHasher:
app/Hashing/Md5Hasher.php
namespace App\Hashing;
use Illuminate\Contracts\Hashing\Hasher;
use Illuminate\Hashing\AbstractHasher;
class Md5Hasher extends AbstractHasher implements Hasher
{
public function make($value, array $options = []): string
{
return md5($value . config('hashing.md5.salt'));
}
public function check($value, $hashedValue, array $options = []): bool
{
return $this->make($value) === $hashedValue;
}
public function needsRehash($hashedValue, array $options = []): bool
{
return false;
}
}Регистрация нового драйвера в приложении
Регистрируем его в методе boot следующего сервис провайдера:
app/Providers/AuthServiceProvider.php
namespace App\Providers;
use App\Hashing\Md5Hasher;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
// ...
public function boot(): void
{
// ...
Hash::extend('md5', static function () {
return new Md5Hasher();
});
}
}Задаём salt для хэширования (опционально)
Ваше легаси приложение может использовать salt для конкатенации перед хэшированием пароля. Мы можем задать её в конфигурации и делегировать значение в .env файл. Если ваше легаси приложение не использует salt, не нужно добавлять его в .env файл.
config/hashing.php
return [
// ...
'md5' => [
'salt' => env('MD5_SALT'),
],
];.env
MD5_SALT=my_saltОбновите пароли
Чтобы перехэшировать пароль, мы можем перехватить попытки пользователей войти в систему и проверить, совпадает ли хэшированный пароль MD5 с паролем в базе данных. Мы можем сделать это, прослушивая событие Illuminate\Auth\Events\Attempting::class
php artisan make:listener UpdateMd5Passwordapp/Providers/EventServiceProvider.php
class EventServiceProvider extends ServiceProvider
{
//...
protected $listen = [
//...
'Illuminate\Auth\Events\Attempting::class' => [
'App\Listeners\UpdateMd5Password::class',
],
];
//...
}Следующая реализация проверяет, соответствуют ли учётные данные устаревшему алгоритму (MD5), и обновляют его до нового. Поток аутентификации продолжается, и пользователь будет успешно аутентифицирован с использованием драйвера по умолчанию (bcrypt).
app/Listeners/UpdateSha1Password.php
namespace App\Listeners;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
class UpdateMd5Password
{
public function handle(object $event): void
{
$user = User::where('email', $event->credentials['email'])->first();
$md5Password = Hash::driver('md5')->make($event->credentials['password']);
if ($user && $user->getAuthPassword() === $md5Password) {
$user->password = Hash::make($event->credentials['password']);
$user->save();
}
}
}В заключение
У вас может быть другой алгоритм хэширования в вашем легаси PHP приложении. Вы можете внести необходимые изменения, чтобы добиться такого же поведения.