是的,您應該遷移到新的API並且不要立即再次使用MD5來實現此目的。
如果你不使用password_hash()
/password_verify()
並希望migrate your code to a more secure method, seamlessly:
- 添加一列以您的用戶帳戶的表,稱爲
legacy_password
(或同等學歷)。
- 計算現有MD5哈希值的bcrypt哈希值並將它們存儲在數據庫中(設置爲
legacy_password
至TRUE
)。
- 修改您的驗證碼以處理遺留標誌。
當用戶嘗試登錄時,首先檢查是否設置了legacy_password
標誌。如果是,則首先預先使用MD5對其密碼進行哈希處理,然後使用此預設值代替其密碼。之後,重新計算 bcrypt散列並將新散列存儲在數據庫中,禁用該過程中的legacy_password
標誌。在PHP 7+非常寬鬆的例子如下:
/**
* This is example code. Please feel free to use it for reference but don't just copy/paste it.
*
* @param string $username Unsafe user-supplied data: The username
* @param string $password Unsafe user-supplied data: The password
* @return int The primary key for that user account
* @throws InvalidUserCredentialsException
*/
public function authenticate(string $username, string $password): int
{
// Database lookup
$stmt = $this->db->prepare("SELECT userid, passwordhash, legacy_password FROM user_accounts WHERE username = ?");
$stmt->execute([$username]);
$stored = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$stored) {
// No such user, throw an exception
throw new InvalidUserCredentialsException();
}
if ($stored['legacy_password']) {
// This is the legacy password upgrade code
if (password_verify(md5($password), $stored['passwordhash'])) {
$newhash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $this->db->prepare("UPDATE user_accounts SET passwordhash = ?, legacy_password = FALSE WHERE userid = ?");
$stmt->execute([$newhash, $stored['userid']]);
// Return the user ID (integer)
return $stored['userid'];
}
} elseif (password_verify($password, $stored['passwordhash'])) {
// This is the general purpose upgrade code e.g. if a future version of PHP upgrades to Argon2
if (password_needs_rehash($stored['passwordhash'], PASSWORD_DEFAULT)) {
$newhash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $this->db->prepare("UPDATE user_accounts SET passwordhash = ? WHERE userid = ?");
$stmt->execute([$newhash, $stored['userid']]);
}
// Return the user ID (integer)
return $stored['userid'];
}
// When all else fails, throw an exception
throw new InvalidUserCredentialsException();
}
用法:
try {
$userid = $this->authenticate($username, $password);
// Update the session state
// Redirect to the post-authentication landing page
} catch (InvalidUserCredentialsException $e) {
// Log the failure
// Redirect to the login form
}
主動升級原有哈希是在一個機會主義策略(換湯不換藥當用戶登錄安全取勝,但離開不安全在非活動用戶的數據庫中散列):使用主動策略,如果您的服務器在所有人再次登錄之前都被入侵,那麼他們的密碼已經使用了可接受的算法(在示例代碼中爲bcrypt)。
上述示例代碼也可用於Bcrypt-SHA-384的風味。
此外,這與encryption無關。
不要使用MD5這是一箇舊的和薄弱的散列。 – Daan
但是,當我使用腳本的password_hash部分時,這是正確的嗎?爲什麼你低估了我? – androidnation
我沒有downvote和是使用'password_hash' – Daan