Laravel Auth结合加密用户表的密码重置链接发送问题
没问题,咱们可以通过重写Laravel密码重置流程里的几个核心类来搞定这个问题,不用完全重构整个流程。下面是具体的操作步骤:
Laravel的密码重置流程依赖PasswordBroker和用户检索相关的逻辑,咱们只需要重写关键部分,就能适配你的email_hash字段需求:
1. 重写PasswordBroker的用户检索逻辑(最直接的方案)
如果只需要在密码重置流程中适配email_hash,最省事的方式是重写PasswordBroker里的getUser方法——这是密码重置时查找用户的核心方法。
首先创建自定义的PasswordBroker类,比如app/Broker/CustomPasswordBroker.php:
<?php namespace App\Broker; use Illuminate\Auth\Passwords\PasswordBroker; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; class CustomPasswordBroker extends PasswordBroker { protected function getUser(array $credentials) { // 把用户输入的邮箱转换成sha256哈希,用email_hash字段检索用户 $user = $this->users->retrieveByCredentials([ 'email_hash' => hash('sha256', $credentials['email']), ]); // 验证用户存在且密码凭证有效 if ($user && $this->validateCredentials($user, $credentials)) { return $user; } return null; } }
接下来要替换默认的PasswordBroker实例,在app/Providers/AuthServiceProvider.php的boot方法里添加注册逻辑:
use App\Broker\CustomPasswordBroker; use Illuminate\Auth\Passwords\PasswordBrokerManager; use Illuminate\Support\Facades\Auth; public function boot() { $this->registerPolicies(); // 注册自定义的密码broker Auth::broker()->extend('custom', function ($app, $config) { $tokens = $app->make('auth.password.tokens'); $users = $app->make('auth')->createUserProvider($config['provider']); return new CustomPasswordBroker($tokens, $users, $app['mailer'], $config['email']); }); }
最后修改config/auth.php里的密码配置,指定使用咱们的自定义broker:
'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, 'broker' => 'custom', // 切换到自定义broker ], ],
2. 确保User模型能返回解密后的邮箱
因为你用了Elocryptfive,你的User模型应该已经有解密email字段的方法了,确保这个方法正常工作:
public function getEmailAttribute($value) { return $this->decryptAttribute($value); }
这样Laravel发送重置邮件时,调用$user->email就能自动拿到解密后的真实邮箱,不用额外修改邮件发送逻辑。
(可选)统一整个认证系统的用户检索逻辑
如果你希望登录、密码重置等所有场景都通过email_hash检索用户,可以再自定义一个UserProvider:
创建app/Providers/CustomEloquentUserProvider.php:
<?php namespace App\Providers; use Illuminate\Auth\EloquentUserProvider; use Illuminate\Contracts\Auth\Authenticatable as UserContract; class CustomEloquentUserProvider extends EloquentUserProvider { public function retrieveByCredentials(array $credentials) { if (empty($credentials) || (count($credentials) === 1 && array_key_exists('password', $credentials))) { return; } // 如果传入的是email,自动转换成email_hash if (isset($credentials['email'])) { $credentials['email_hash'] = hash('sha256', $credentials['email']); unset($credentials['email']); } $query = $this->createModel()->newQuery(); foreach ($credentials as $key => $value) { if (strpos($key, 'password') === false) { $query->where($key, $value); } } return $query->first(); } }
然后在AuthServiceProvider的boot方法里注册这个provider:
use App\Providers\CustomEloquentUserProvider; use Illuminate\Support\Facades\Auth; public function boot() { $this->registerPolicies(); // 注册自定义用户provider Auth::provider('custom-eloquent', function ($app, array $config) { return new CustomEloquentUserProvider($app['hash'], $config['model']); }); }
最后修改config/auth.php的provider配置:
'providers' => [ 'users' => [ 'driver' => 'custom-eloquent', // 切换到自定义provider 'model' => App\User::class, ], ],
完成以上步骤后,密码重置流程就能正常工作了:用户输入邮箱,系统自动转换成email_hash检索用户,找到后用解密后的邮箱发送重置链接,完全不用重写视图或控制器逻辑。
内容的提问来源于stack exchange,提问作者gbalduzzi

