我花了幾天時(shí)間對(duì) Laravel 9 中某些密碼驗(yàn)證失敗進(jìn)行故障排除。密碼 testperson
解析為哈希值 $2y$10$5xc/wAmNCKV.YhpWOfyNoetCj/r3Fs5TyAskgZuIF/LEItWfm7rPW
。對(duì)相應(yīng)數(shù)據(jù)庫(kù)表的直接查詢可確認(rèn)這是正確的哈希值。然而 Laravel 的身份驗(yàn)證基礎(chǔ)設(shè)施拒絕此密碼并拒絕身份驗(yàn)證。
這并不普遍。我有多個(gè)可以正確解析的密碼。例如,密碼 eo
解析為 $2y$10$uNWYvMVmagIwQ2eXnVKLCOAK1QFQdcRtxbvlghf.Xpg0U1w.N./N2
,并且 Laravel 會(huì)驗(yàn)證該密碼。相同的機(jī)制創(chuàng)建這兩個(gè)用戶記錄,盡管它們具有不同的權(quán)限(由記錄上的布爾值指示)。
我找到了函數(shù) password_verify
的錯(cuò)誤,該函數(shù)被確定為在此 Stack Overflow 問(wèn)題和此 Treehouse 線程中返回漏報(bào)。
具體來(lái)說(shuō),這是 Laravel 中出現(xiàn)此故障點(diǎn)的堆棧:
login
路由通過(guò)控制器類調(diào)用 \Illuminate\Foundation\Auth\AuthenticatesUsers::login
。login
方法調(diào)用 \Illuminate\Foundation\Auth\AuthenticatesUsers::attemptLogin
。attemptLogin
方法調(diào)用控制器守衛(wèi)對(duì)象的 attempt
方法。\Illuminate\Auth\SessionGuard::attempt
調(diào)用 \Illuminate\Auth\SessionGuard::hasValidCredentials
。\Illuminate\Auth\SessionGuard::hasValidCredentials
調(diào)用守衛(wèi)提供者對(duì)象上的 validateCredentials
方法。Illuminate\Auth\EloquentUserProvider::validateCredentials
在其 hasher 對(duì)象上調(diào)用 check
方法。Illuminate\Hashing\HashManager::check
在其驅(qū)動(dòng)程序上調(diào)用 check
方法。Illuminate\Hashing\BcryptHasher::check
調(diào)用 Illuminate\Hashing\AbstractHasher::check
。Illuminate\Hashing\AbstractHasher::check
調(diào)用 password_verify
。展開(kāi)整個(gè)堆棧后,我在登錄控制器的 login
方法中運(yùn)行以下代碼:
$provider = $this->guard()->getProvider(); $credentials = $this->credentials($request); $user = $provider->retrieveByCredentials($credentials); $password_unhashed = $request['password']; $password_hashed = $user->getAuthPassword(); $password_verify = password_verify($password_unhashed, $password_hashed); logger('attemping login', compact('password_verify','password_unhashed','password_hashed'));
轉(zhuǎn)儲(chǔ)此上下文:
{ "password_verify": false, "password_unhashed": "testperson", "password_hashed": "yxc/wAmNCKV.YhpWOfyNoetCj/r3Fs5TyAskgZuIF/LEItWfm7rPW" }
如果我將該密碼放入 SELECT users WHERE password=
查詢中,我就會(huì)得到我期望的用戶。
這是怎么回事?我該如何解決這個(gè)問(wèn)題?
我認(rèn)為您關(guān)于您提供的哈希值是“testperson”哈希值的斷言實(shí)際上是錯(cuò)誤的。由于散列是單向的,因此我無(wú)法告訴您所顯示的散列是從何而來(lái)的。注意:它在 PHP 7.4 上運(yùn)行,但我認(rèn)為它不會(huì)在 PHP 8 及更高版本上運(yùn)行,因?yàn)?passwd_hash() 中的 salt 選項(xiàng)已被棄用。
10, "salt" => substr($testhash, 7, 22)); $pwhash = password_hash($password, PASSWORD_BCRYPT, $options); echo $pwhash."\n"; $salt = substr($pwhash, 0, 29); echo $salt."\n"; $cryptpw = crypt($password, $salt); echo $cryptpw."\n"; if (password_verify($password, $cryptpw)) { echo("Verified.\n"); } else { echo("NOT Verified.\n"); } if (password_needs_rehash($cryptpw, PASSWORD_BCRYPT, $options)) { echo("Needs rehash.\n"); } else { echo("Doesn't need rehash.\n"); } /* testperson results... yxc/wAmNCKV.YhpWOfyNoeVNPMEcYrxepQeFAssFoAaIYs4WLmgZO yxc/wAmNCKV.YhpWOfyNoe yxc/wAmNCKV.YhpWOfyNoeVNPMEcYrxepQeFAssFoAaIYs4WLmgZO Verified. Doesn't need rehash. eo results... y$uNWYvMVmagIwQ2eXnVKLCOAK1QFQdcRtxbvlghf.Xpg0U1w.N./N2 y$uNWYvMVmagIwQ2eXnVKLCO y$uNWYvMVmagIwQ2eXnVKLCOAK1QFQdcRtxbvlghf.Xpg0U1w.N./N2 Verified. Doesn't need rehash. */ ?>