此函式無法檢查字串是否為 MD5 或 SHA1 雜湊值。它只能告訴您使用 password_hash 函式雜湊的密碼是否需要再次通過雜湊函式以跟上新的預設值。
您可以使用此函式的唯一時機是在使用者登入且您已透過 password_verify 確認輸入的密碼確實正確時。此時,如果 password_needs_rehash 傳回 true,您可以將明文密碼通過 password_hash 函式。
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
password_needs_rehash — 檢查給定的雜湊值是否符合給定的選項
此函式會檢查提供的雜湊值是否符合提供的演算法和選項。如果不是,則假設雜湊值需要重新雜湊。
hash
由 password_hash() 建立的雜湊值。
algo
一個密碼演算法常數,表示雜湊密碼時要使用的演算法。
options
包含選項的關聯式陣列。有關每個演算法支援的選項說明,請參閱密碼演算法常數。
範例 #1 password_needs_rehash() 的用法
<?php
$password = 'rasmuslerdorf';
$hash = '$2y$10$YCFsG6elYca568hBi2pZ0.3LDL5wjgxct1N8w/oLR/jfHsiQwCqTS';
$algorithm = PASSWORD_BCRYPT;
// 隨著硬體的提升,bcrypt 的成本參數會隨著時間而改變
$options = ['cost' => 12];
// 驗證儲存的雜湊值與明文密碼是否相符
if (password_verify($password, $hash)) {
// 檢查演算法或選項是否已更改
if (password_needs_rehash($hash, $algorithm, $options)) {
// 如果是,則建立新的雜湊值,並取代舊的雜湊值
$newHash = password_hash($password, $algorithm, $options);
// 使用 $newHash 更新使用者紀錄
}
// 執行登入。
}
?>
此函式無法檢查字串是否為 MD5 或 SHA1 雜湊值。它只能告訴您使用 password_hash 函式雜湊的密碼是否需要再次通過雜湊函式以跟上新的預設值。
您可以使用此函式的唯一時機是在使用者登入且您已透過 password_verify 確認輸入的密碼確實正確時。此時,如果 password_needs_rehash 傳回 true,您可以將明文密碼通過 password_hash 函式。
此函式確實可以用於協助透明地更新舊版密碼(那些未使用 password_hash() 函式的密碼 - 例如:可能使用 MD5 或 SHA1 的某些東西)
在舊版網站中,驗證使用者身份時(登入期間),請先使用 password_verify() 檢查密碼。如果失敗,可能只是因為使用者的密碼雜湊值是很久以前由舊版或自製的密碼演算法建立的。
然後,您可以使用網站的舊版密碼演算法重新檢查密碼。如果也失敗了,則登入失敗,因為提供的密碼未通過新密碼或舊密碼測試的驗證。
如果這兩個測試其中之一成功,就表示密碼正確,您接著應該對儲存的雜湊值呼叫 password_needs_rehash() 函式。它會正確指出密碼雜湊值是否需要重新計算,原因可能是雜湊值無法辨識(舊版),或是由 password_hash() 建立的現代雜湊值,可能只是需要更新其成本指數。
只需將重新計算的雜湊值儲存在資料庫中,您就擁有了與 password_verify() 相容的使用者密碼,並且在未來的登入中可以跳過第二個測試(但仍需檢查是否需要重新雜湊)。
password_needs_rehash 函式的其他一些使用案例是當您指定使用 PASSWORD_DEFAULT 演算法進行 password_hash 時。
如「密碼雜湊預定義常數」和 password_hash 頁面所述,PASSWORD_DEFAULT 使用的演算法會隨著不同版本的 PHP 發佈而改變。
此外,如果您更改了 password_hash 選項中可選的成本或靜態鹽(請勿使用靜態鹽)的要求,則會使用 password_needs_rehash。
完整範例
<?php
$new = [
'options' => ['cost' => 11],
'algo' => PASSWORD_DEFAULT,
'hash' => null
];
$password = 'rasmuslerdorf';
//儲存的密碼雜湊值
$oldHash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';
//驗證儲存的雜湊值與明文密碼
if (true === password_verify($password, $oldHash)) {
//驗證舊版密碼與新的 password_hash 選項
if (true === password_needs_rehash($oldHash, $new['algo'], $new['options'])) {
//使用新的雜湊重新雜湊/儲存明文密碼
$newHash = password_hash($password, $new['algo'], $new['options']);
echo $newHash;
}
}
?>
上述範例將輸出類似以下內容
$2y$11$Wu5rN3u38.g/XWdUeA6Wj.PD.F0fLXXmZrMNFyzzg2UxkVmxlk41W