Laravel事件监听中如何发送未加密的用户密码至邮件
问题场景
管理员创建用户时会自动生成明文密码,哈希后存入数据库,但通过UserCreated事件传递的User模型无法获取明文密码,导致邮件无法发送完整的登录凭证。
现有代码如下:
EventServiceProvider 配置
protected $listen = [ 'App\Events\UserCreated' => [ 'App\Listeners\SendCredentials' ], ];
UserCreated 事件
class UserCreated { use Dispatchable, InteractsWithSockets, SerializesModels; public $user; /** * Create a new event instance. * * @return void */ public function __construct($user) { $this->user = $user; } }
SendCredentials 监听器
class SendCredentials { /** * Handle the event. * * @param \App\Events\UserCreated $event * @return void */ public function handle(UserCreated $event) { $user = $event->user; Mail::to($user->email)->send(new SendUserMail($user)); } }
触发事件的代码
public function createUser(){ $this->validate(); $randomPass = Str::random(8); $userCreds = ['email' => $this->email, 'password' => $randomPass]; try{ $test = User::firstOrCreate([ 'name' => $this->name, 'email' => $this->email, 'password' => Hash::make($randomPass), 'email_verified_at' => Carbon::now(), 'user_type' => (int)$this->selectedUser, 'assigned_to' => (int)$this->selectedAssigned, 'doctor_type' => $this->selectTypeDoc, ]); // Mail::to($this->email)->send(new SendUserMail($userCreds)); UserCreated::dispatch($test); $this->reset(); $this->emitUp('refreshParent'); $this->dispatchBrowserEvent('swal-insert'); }catch(\Exception $e){ $this->dispatchBrowserEvent('createUser-error'); } $this->closeModal(); }
核心问题:如何在邮件中发送未加密的明文密码?
解决方案
方法一:修改事件,同时传递User模型和明文密码
- 更新
UserCreated事件,新增明文密码属性:
class UserCreated { use Dispatchable, InteractsWithSockets, SerializesModels; public $user; public $plainPassword; // 新增明文密码属性 public function __construct($user, $plainPassword) { $this->user = $user; $this->plainPassword = $plainPassword; } }
- 触发事件时传入明文密码:
// 替换原触发代码 UserCreated::dispatch($test, $randomPass);
- 更新监听器,将明文密码传给邮件:
class SendCredentials { public function handle(UserCreated $event) { $user = $event->user; $plainPassword = $event->plainPassword; Mail::to($user->email)->send(new SendUserMail([ 'user' => $user, 'password' => $plainPassword ])); } }
方法二:临时给User模型添加明文密码属性
这种方法不需要修改事件构造参数,在创建用户后给模型临时赋值(不会存入数据库):
- 在
createUser方法中添加临时属性:
$test = User::firstOrCreate([ // 现有字段配置 ]); // 临时添加明文密码属性 $test->plain_password = $randomPass; UserCreated::dispatch($test);
- 监听器中直接读取该属性:
public function handle(UserCreated $event) { $user = $event->user; Mail::to($user->email)->send(new SendUserMail([ 'user' => $user, 'password' => $user->plain_password ])); }
方法三:直接传递凭证数组给事件
如果不需要整个User模型,可直接传递包含明文密码和用户信息的数组:
- 修改
UserCreated事件:
class UserCreated { use Dispatchable, InteractsWithSockets, SerializesModels; public $credentials; public function __construct($credentials) { $this->credentials = $credentials; } }
- 触发事件时传入包含用户模型和明文密码的数组:
$userCreds = [ 'email' => $this->email, 'password' => $randomPass, 'user' => $test // 加入User模型用于邮件展示用户信息 ]; UserCreated::dispatch($userCreds);
- 监听器中直接使用该数组:
public function handle(UserCreated $event) { $creds = $event->credentials; Mail::to($creds['email'])->send(new SendUserMail($creds)); }
内容的提问来源于stack exchange,提问作者cdBreak
相关产品推荐
相关产品推荐

