PHP 用户密码重新哈希 Class (MySQL)
PHP Password Rehashing in User Class (MySQL)
所以我正在处理合并功能,以重新散列以升级用户以获得 bcrypt 密码,到现有的 class 我发现并设置得相当成功,这太棒了。
但是,此 class 缺少重新散列检查,这对于现有用户数据库中的遗留密码来说非常糟糕。我们需要处理 SHA1 密码!我们使用 SHA1 + Salt,所以我希望这可以转换。
我正在使用这里找到的 class:
https://alexwebdevelop.com/user-authentication/
因此使用此 class,我添加了以下 public 函数:
public function authenticate($username, $password)
{
/* Global $pdo object */
global $pdo;
// Database lookup
$stmt = $pdo->prepare("SELECT id, password, legacy_password FROM users WHERE username = ?");
$stmt->execute([$username]);
$stored = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$stored) {
// No such user, throw an exception
throw new Exception('Invalid user.');
}
if ($stored['legacy_password']) {
// This is the legacy password upgrade code
if (password_verify(sha1($password), $stored['password'])) {
$newHash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("UPDATE users SET password = ?, legacy_password = FALSE WHERE id = ?");
$stmt->execute([$newhash, $stored['id']]);
// Return the user ID (integer)
return $stored['id'];
}
} elseif (password_verify($password, $stored['password'])) {
// This is the general purpose upgrade code e.g. if a future version of PHP upgrades to Argon2
if (password_needs_rehash($stored['password'], PASSWORD_DEFAULT)) {
$newhash = password_hash($password, PASSWORD_BCRYPT);
$stmt = $pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
$stmt->execute([$newhash, $stored['id']]);
}
// Return the user ID (integer)
return $stored['id'];
}
// When all else fails, throw an exception
throw new Exception('Rehashing failed.');
}
现在在 class 的 login() 函数中,我已经替换了
public function login($name, $passwd)
{
...
if (is_array($row)) {
if (password_verify($passwd, $row['password'])) {
/* Authentication succeeded. Set the class properties (id and name) */
$this->id = intval($row['id'], 10);
$this->name = $name;
$this->authenticated = TRUE;
/* Register the current Sessions on the database */
$this->registerLoginSession();
/* Finally, Return TRUE */
return TRUE;
}
}
}
有了这个:
public function login($name, $passwd)
{
...
if (is_array($row)) {
$userid = $this->authenticate($name, $row['password']);
if (password_verify($passwd, $row['password'])) {
/* Authentication succeeded. Set the class properties (id and name) */
$this->id = intval($userid);
$this->name = $name;
$this->authenticated = TRUE;
/* Register the current Sessions on the database */
$this->registerLoginSession();
/* Finally, Return TRUE */
return TRUE;
}
}
}
所以它应该 return 在检查/重新散列后交回 ID。所以它发现我是一个用户,经过测试。很好.. 所以现在所有 authenticate() 所做的就是抛出失败的异常错误。我不知道如何从中获取错误消息。
这似乎正是与此 ID 相关的事情,我做错了什么?
这一点: 用户使用 SHA1(加盐)密码形式登录,脚本重新哈希密码,用户登录就像什么都没发生一样。
authenticate() 我使用的转换函数:
https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016#legacy-hashes
非常抱歉!我从这里的建议中学到了很多,感谢所有的帮助!
所以我自己解决了这个问题。我所做的是删除 authenticate() 函数,而是根据反馈意见直接解决这个问题(我完全同意)。
我将 post 中的最后一个代码块替换为:
if (is_array($row)) {
if (password_needs_rehash($row['password'], PASSWORD_DEFAULT)) {
$newhash = password_hash($passwd, PASSWORD_BCRYPT);
$stmt = $pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
$stmt->execute([$newhash, $row['id']]);
}
if (password_verify($passwd, $row['password'])) {
/* Authentication succeeded. Set the class properties (id and name) */
$this->id = intval($row['id'], 10);
$this->name = $name;
$this->authenticated = TRUE;
/* Register the current Sessions on the database */
$this->registerLoginSession();
/* Finally, Return TRUE */
return TRUE;
}
}
并且用户密码正在重新哈希,并正在登录!
所以我正在处理合并功能,以重新散列以升级用户以获得 bcrypt 密码,到现有的 class 我发现并设置得相当成功,这太棒了。
但是,此 class 缺少重新散列检查,这对于现有用户数据库中的遗留密码来说非常糟糕。我们需要处理 SHA1 密码!我们使用 SHA1 + Salt,所以我希望这可以转换。
我正在使用这里找到的 class:
https://alexwebdevelop.com/user-authentication/
因此使用此 class,我添加了以下 public 函数:
public function authenticate($username, $password)
{
/* Global $pdo object */
global $pdo;
// Database lookup
$stmt = $pdo->prepare("SELECT id, password, legacy_password FROM users WHERE username = ?");
$stmt->execute([$username]);
$stored = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$stored) {
// No such user, throw an exception
throw new Exception('Invalid user.');
}
if ($stored['legacy_password']) {
// This is the legacy password upgrade code
if (password_verify(sha1($password), $stored['password'])) {
$newHash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("UPDATE users SET password = ?, legacy_password = FALSE WHERE id = ?");
$stmt->execute([$newhash, $stored['id']]);
// Return the user ID (integer)
return $stored['id'];
}
} elseif (password_verify($password, $stored['password'])) {
// This is the general purpose upgrade code e.g. if a future version of PHP upgrades to Argon2
if (password_needs_rehash($stored['password'], PASSWORD_DEFAULT)) {
$newhash = password_hash($password, PASSWORD_BCRYPT);
$stmt = $pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
$stmt->execute([$newhash, $stored['id']]);
}
// Return the user ID (integer)
return $stored['id'];
}
// When all else fails, throw an exception
throw new Exception('Rehashing failed.');
}
现在在 class 的 login() 函数中,我已经替换了
public function login($name, $passwd)
{
...
if (is_array($row)) {
if (password_verify($passwd, $row['password'])) {
/* Authentication succeeded. Set the class properties (id and name) */
$this->id = intval($row['id'], 10);
$this->name = $name;
$this->authenticated = TRUE;
/* Register the current Sessions on the database */
$this->registerLoginSession();
/* Finally, Return TRUE */
return TRUE;
}
}
}
有了这个:
public function login($name, $passwd)
{
...
if (is_array($row)) {
$userid = $this->authenticate($name, $row['password']);
if (password_verify($passwd, $row['password'])) {
/* Authentication succeeded. Set the class properties (id and name) */
$this->id = intval($userid);
$this->name = $name;
$this->authenticated = TRUE;
/* Register the current Sessions on the database */
$this->registerLoginSession();
/* Finally, Return TRUE */
return TRUE;
}
}
}
所以它应该 return 在检查/重新散列后交回 ID。所以它发现我是一个用户,经过测试。很好.. 所以现在所有 authenticate() 所做的就是抛出失败的异常错误。我不知道如何从中获取错误消息。
这似乎正是与此 ID 相关的事情,我做错了什么?
这一点: 用户使用 SHA1(加盐)密码形式登录,脚本重新哈希密码,用户登录就像什么都没发生一样。
authenticate() 我使用的转换函数:
https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016#legacy-hashes
非常抱歉!我从这里的建议中学到了很多,感谢所有的帮助!
所以我自己解决了这个问题。我所做的是删除 authenticate() 函数,而是根据反馈意见直接解决这个问题(我完全同意)。
我将 post 中的最后一个代码块替换为:
if (is_array($row)) {
if (password_needs_rehash($row['password'], PASSWORD_DEFAULT)) {
$newhash = password_hash($passwd, PASSWORD_BCRYPT);
$stmt = $pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
$stmt->execute([$newhash, $row['id']]);
}
if (password_verify($passwd, $row['password'])) {
/* Authentication succeeded. Set the class properties (id and name) */
$this->id = intval($row['id'], 10);
$this->name = $name;
$this->authenticated = TRUE;
/* Register the current Sessions on the database */
$this->registerLoginSession();
/* Finally, Return TRUE */
return TRUE;
}
}
并且用户密码正在重新哈希,并正在登录!