I have the following function that I use to check a user login, at it’s state it can only check the username and the password:
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);
}
}
}
}
Making abstraction of all the functions that are included there and other variables, I need to know if I can make this function work for the username as well for the email.
What I mean is, I want to give the user the chance to login either by his / her email or by his / her username. Is that possible to do to my function, and if yes how ?
It sounds like you want
WHERE (user_username = ? OR user_email = ?).You will need to retrieve the salt from the database, though.
Best practice is to use a long sequence of cryptographically secure random bytes as salt, not the username, so you should be doing that anyway.