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