如何在用户首次使用 Laravel Passport 登录时安全地将 MD5 哈希密码迁移到 bcrypt?

问题描述 投票:0回答:1

我有一个 Laravel 应用程序,最近我从旧系统迁移了用户。旧系统中的密码是使用 MD5 进行哈希处理的。

我已经成功实现了使用 Laravel Sanctum 进行本地登录的解决方案。在此解决方案中,我扩展了 EloquentUserProvider,并在 validateCredentials() 方法中,根据 MD5 检查密码。如果它是 MD5 哈希值,我会对其进行 bcrypt 并保存。

但是,在尝试使用 Laravel Passport 进行 API 身份验证实现相同功能时,我遇到了困难。尽管我尝试扩展 PassportUserProvider 和 PassportServiceProvider,但我一直无法让它工作。我开始担心我可能错误地处理了这个问题。有人可以指导如何进行吗?

这是我的尝试之一:

<?php
// Path: app/Providers/PassportUserProvider.php

namespace App\Providers;

use Laravel\Passport\PassportUserProvider as BasePassportUserProvider;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;

use Log;

class PassportUserProvider extends BasePassportUserProvider implements UserProvider
{
    /**
     * Validate a user against the given credentials.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  array  $credentials
     * @return bool
     */
    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        Log::build(['driver' => 'single', 'path' => storage_path('logs/MD5_rehashed.log'),])->info('PassportUserProvider Attempting to check MD5.');

        $plain = $credentials['password'];

        // Check if the password is MD5 hashed
        if ($this->isMD5($user->getAuthPassword())) {
            // Retrieve the user model by ID using Laravel's default user provider
            $userModel = $this->retrieveById($user->getAuthIdentifier());

            // If the user exists and MD5 password matches, update the password
            if ($userModel && $this->checkMD5Password($plain, $userModel)) {
                $userModel->password = bcrypt($plain);
                $userModel->save();

                Log::build(['driver' => 'single', 'path' => storage_path('logs/MD5_rehashed.log'),])->info('#' . $userModel->id);

                return true;
            }
        }

        // If password is not MD5 hashed, or MD5 validation fails, fall back to default validation
        return parent::validateCredentials($user, $credentials);
    }

    /**
     * Check if the password is MD5 hashed.
     *
     * @param string $password
     * @return bool
     */
    protected function isMD5($password)
    {
        return preg_match('/^[a-f0-9]{32}$/', $password);
    }

    /**
     * Check if the plain password matches the MD5 hash.
     *
     * @param string $plain
     * @param \Illuminate\Contracts\Auth\Authenticatable $userModel
     * @return bool
     */
    protected function checkMD5Password($plain, $userModel)
    {
        // Implement your MD5 password check logic here
        // Example:
        return md5($plain) === $userModel->getAuthPassword();
    }
}

...将其绑定到 AuthServiceProvider 的启动中或像这样注册:

   $this->app->bind(
       \Laravel\Passport\PassportUserProvider::class,
       \App\Providers\PassportUserProvider::class
   );
laravel authentication md5 laravel-passport
1个回答
0
投票

就这么简单:

自定义密码验证

所以在使用的用户模型中:

    public function validateForPassportPasswordGrant(string $password): bool
{
    // Check if the stored password is MD5 hashed
    if (preg_match('/^[a-f0-9]{32}$/', $this->password)) {
        $hash = md5($password);
        
        // If the password matches the MD5 hash, bcrypt the new password and update it and return true
        if ($hash === $this->password) {
            $this->password = bcrypt($password);
            $this->save();
            return true;
        } else {
            // If the password does not match the MD5 hash, return false
            return false;
        }
    } else {
        // If the stored password is not MD5 hashed, use default
        return Hash::check($password, $this->password);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.