Php 在数据库中存储时使用MD5和密码哈希函数
如果我有用于登录系统的PHP脚本:Php 在数据库中存储时使用MD5和密码哈希函数,php,encryption,pdo,hash,Php,Encryption,Pdo,Hash,如果我有用于登录系统的PHP脚本: $user = $_POST['user_name']; $pass = md5($_POST['user_pass']); require_once("connection_file.php"); $sql = "SELECT * FROM login_table WHERE user_n = :us AND user_p = :password"; $stmt = $conn->prepare($sql);
$user = $_POST['user_name'];
$pass = md5($_POST['user_pass']);
require_once("connection_file.php");
$sql = "SELECT * FROM login_table WHERE user_n = :us AND user_p = :password";
$stmt = $conn->prepare($sql);
$stmt->bindValue(':us', $user, PDO::PARAM_STR);
$stmt->bindValue(':password', $pass, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchAll();
if($result)
{
//echo $msg = "user exist";
if(session_status() == PHP_SESSION_NONE)
{
session_start();
foreach($result as $row)
{
$hash = password_hash($row['user_pass'], PASSWORD_BCRYPT);
if(password_verify($row['user_pass'], $hash))
{
$_SESSION['userid'] = $row['user_id'];
$_SESSION['role'] = $row['user_role'];
header("Location: homepage.php");
}
}
}
}
else
{
$msg = "Wrong credentials";
header("Location: login_page.php");
}
正如您所看到的,我已经在数据库中将我的密码保存为MD5
,并且我正在使用$pass=MD5($\u POST['user\u pass'])
验证用户输入的文本是否等于MD5
hash
password\u hash
和password\u verify
?或者使用MD5
就足够了是的,您应该立即迁移到新的API,并且不再为此目的使用MD5
如果您没有使用
password\u hash()
/password\u verify()
并希望:
legacy\u password
(或等效项)legacy\u password
设置为TRUE
)legacy\u 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)
上面的示例代码在flavor中也可用
此外,这与此无关。是的,您应该立即迁移到新的API,并且不再为此目的使用MD5
如果您没有使用
password\u hash()
/password\u verify()
并希望:
legacy\u password
(或等效项)legacy\u password
设置为TRUE
)legacy_password
标志。如果设置了,首先使用MD5对其密码进行预哈希,然后使用此预哈希值代替其密码。然后,重新计算bcrypt哈希并将新哈希存储在数据库中,在此过程中禁用legacy_password
标志。aPHP 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)
上面的示例代码在flavor中也可用
另外,这与此无关。不要使用MD5。这是一个陈旧而脆弱的散列。但当我使用脚本中的密码散列部分时,这是正确的?为什么你否决了我?所以你使用密码散列,但问是否可以改为使用MD5。这个问题对我来说毫无意义。不,如果你真的需要答案。如果你尝试使用密码散列很有可能你最终会让它变得更加不安全。(尽管每个人都会本能地对此投反对票,但这是一个关于密码哈希迁移的问题。他们已经知道不要使用MD5。)不要使用MD5,这是一个古老而脆弱的散列。但是当我使用脚本中的密码散列部分时,它是正确的?为什么你否决了我?所以你使用密码散列,但问是否可以使用MD5。这个问题对我来说毫无意义。不,如果你真的需要答案。如果你尝试使用一个组合,很可能你最终会成功r不太安全。(尽管每个人都会本能地对此投反对票,但这是一个关于密码散列迁移的问题。他们已经知道不要使用MD5。)