Auth::logoutOtherDevices 导致密码错误问题
注:经 [@ALMAS](https://learnku.com/users/7036) 提醒,发现user模型中有定义一个修改器,用于密码处理,问题出在该处,并非laravel 问题。特此纠正,感谢 [@ALMAS](https://learnku.com/users/7036) 的提醒。
代码如下:
public function setPasswordAttribute($value)
{
$value = str_replace(' ', '', $value);
$this->attributes['password'] = bcrypt($value);
}
以上纠正于:2019年7月16日 20:32分!
最近做开发的时候,要求实现单设备登录功能,看了下文档,发现 Auth::logoutOtherDevices($password) 正好满足条件。于是兴冲冲的使用了该方法。结果悲剧了, 账号登录后,Auth::logoutOtherDevices 处理完,再想登录的时候,报密码错误。找问题发现使用 Auth::logoutOtherDevices 后,数据库中的密码变了,用 password_verify 去验证数据库中改变后的密码,死活验证不通过。 好嘛,只能跟踪源码找问题了。
/**
* Invalidate other sessions for the current user.
*
* The application must be using the AuthenticateSession middleware.
*
* @param string $password
* @param string $attribute
* @return bool|null
*/
public function logoutOtherDevices($password, $attribute = 'password')
{
if (! $this->user()) {
return;
}
$result = tap($this->user()->forceFill([
**$attribute => Hash::make($password),**
]))->save();
if ($this->recaller() ||
$this->getCookieJar()->hasQueued($this->getRecallerName())) {
$this->queueRecallerCookie($this->user());
}
$this->fireOtherDeviceLogoutEvent($this->user());
return $result;
}
在该方法中,发现密码是Hash::make加密后存储。刚开始以为是这里加密方式问题,后来经测试发现不是。真正的原因是密码被加密了两次,$attribute => Hash::make($password) 加密了一次,在入库的时候又做了一次hash,最终导致密码验证不通过。找到问题就简单了,直接改成如下代码,问题解决。
$result = tap($this->user()->forceFill([
**$attribute => $password,**
]))->save();
初次发文,请多关照!
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu
Laravel多少版本有这个功能?
话说入库时怎么会再hash一次?是不是自己写了修改器?
直接改源码有点不妥吧,可以复写这个方法吗?
此方法要求用户提供其当前密码,你的应用程序应通过输入表单接受该密码:
应该把未加密的密码传进去吧
**这是什么语法@lovecn 前后的**号,只是想做一个提示,不是语法。。。 :joy:
@longren610 大佬,这个forceFill是个静态方法吗?没找到源码在哪里啊
@nullable 我也只是一只刚接触laravel不久的菜鸟 :joy: 不是大佬啦。如果是laravel5.8的话,这个forceFill 在 vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php 里面,第347行
我用的是自带的Auth,只要在LoginController里重写authenticated方法就可以了
然后我又碰到了一个问题:在使用
登录时,怎么退出其它设备的登录状态?
app接口不能用这个嘛
@test-1 不能,app验证用的是token,这个其实是每次登录,将密码重新计算一次hash值,存入用户表中,web登录状态检测到用户表中密码字段值变了,就会把用户踢下线。而app登录状态一般都是用token,要实现其实也简单,在用户登录的时候同时修改一下app用的token就行了。
我也遇到了这个问题,我传了未加密的密码进去,我同时登录两台设备,数据库密码还是别改了。 Auth::guard('money')->logoutOtherDevices($validatedData['password']);