Auth::logoutOtherDevices 導致密碼錯誤問題

longren610發表於2019-07-10

注:經 [@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 協議》,轉載必須註明作者和本文連結

相關文章