我有以下功能,用于检查用户登录,在其状态下,它只能检查用户名和密码:
public function checkUserLogin($username, $password) {
$password = hash_hmac('sha512', $password, $this->salt($username, $password));
$sql = 'SELECT user_username,user_level FROM users WHERE user_username = ? AND user_password = ?';
// Check Login Attempts
if (isset($_SESSION['attempts']) && $_SESSION['attempts'] >= NUMBER_OF_ATTEMPTS) {
$lockdown = true;
$message['lockdown'] = true;
$message['message'] = SYSTEM_LOCKDOWN_MESSAGE;
return json_encode($message);
} else {
if ($stmt = $this->connect->prepare($sql)) {
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
$stmt->bind_result($username, $admin);
if ($stmt->fetch()) {
$_SESSION['member_logged_in'] = true;
$_SESSION['username'] = $username;
$_SESSION['admin'] = $admin;
$_SESSION['attempts'] = 0;
$stmt->close();
$ip = $this->getIP();
$sql = "UPDATE users SET user_last_login_date = NOW(), user_last_login_ip = '$ip' WHERE user_username = '$username'";
if ($stmt = $this->connect->prepare($sql)) {
$stmt->execute();
$stmt->close();
} else {
$error = true;
$message['error'] = true;
$message['message'] = CANNOT_PREPARE_DATABASE_CONNECTION_MESSAGE;
return json_encode($message);
}
$error = false;
if($_SESSION['admin']==1){
$message['level'] = true;
}
$message['error'] = false;
$message['message'] = SUCCESFUL_LOGIN_MESSAGE;
return json_encode($message);
} else {
@$_SESSION['attempts'] = $_SESSION['attempts'] + 1;
$error = true;
$message['error'] = true;
$message['message'] = FAILED_LOGIN_MESSAGE;
return json_encode($message);
}
}
}
}
通过对其中包含的所有函数和其他变量进行抽象,我需要知道是否可以使该函数适用于用户名和电子邮件。
我的意思是,我想让用户有机会通过他的/她的电子邮件或他的/她的用户名登录。这对我的功能有可能吗?如果有,怎么做?
听起来你想要WHERE (user_username = ? OR user_email = ?)
。
不过,您需要从数据库中检索salt
最佳实践是使用加密安全随机字节的长序列作为salt,而不是用户名,所以无论如何都应该这样做。
我想您可以修改查询,根据数据库中的用户名和电子邮件字段检查$username,例如
SELECT user_username,user_level
FROM users
WHERE (? IN (user_username, user_email)) AND user_password = ?';
检查是否存在@
并相应地更改查询:
if (strpos($username, '@') === false) {
$nameField = 'user_username';
} else {
$nameField = 'user_email';
}
$sql = 'SELECT user_username,user_level FROM users WHERE '.$nameField.' = ? AND user_password = ?';
另一个问题是salt是基于用户名的。如果用户决定切换到电子邮件地址,这显然会失败。正如建议的那样,使用一个单独的salt(与用户名无关),并提前添加一个额外的查询来检索它
$query = "
SELECT
`user_username`,
`user_level`
FROM
`users`
WHERE
(
`users`.`user_username` = '".mysql_real_escape_string($user)."'
AND
`users`.`user_password` = '".mysql_real_escape_string($pass)."'
)
OR (
`users`.`user_email` = '".mysql_real_escape_string($user)."'
AND
`users`.`user_password` = '".mysql_real_escape_string($pass)."'
)
";
只需像这样进行查询。我建议使用mysql_real_sescape_string,因为它可以更好地保护您的代码免受SQL注入的影响(请阅读!)。
从这一点开始,您可以继续使用您的代码。