如何使此功能也适用于用户名或电子邮件


How to make this function work for a username or email as well?

我有以下功能,用于检查用户登录,在其状态下,它只能检查用户名和密码:

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注入的影响(请阅读!)。

从这一点开始,您可以继续使用您的代码。

相关文章: