我有一个 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
);
就这么简单:
所以在使用的用户模型中:
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);
}
}