Перенос паролей из легаси PHP приложения в Laravel

Источник: «Migrate passwords from a legacy PHP application to Laravel»
Для переноса легаси 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 UpdateMd5Password

app/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 приложении. Вы можете внести необходимые изменения, чтобы добиться такого же поведения.

Дополнительные материалы

Предыдущая Статья

Техники рефакторинга CSS

Следующая Статья

Понимание CSS медиа-запросов