I want only verified accounts logging in to my website and therefore I've set up and a category called Verification which can either be 0(not verified) or 1(verified) in PHPMyAdmin. Ive gotten it to work so that it changes the value when the account is verified but I cant figure out how to check if the account's "Verification" is 1 or 0. I tried doing this but with no success:
What I've tried
$test = "SELECT Verification FROM users WHERE Verification = 1 AND users_uid = $uid";
if($test == false){
$test = null;
header("location: ../LoginPage.php?error=accountNotVerified");
exit();
}
And here is the whole code if this helps to clear anything up for you.
The whole code(This code works fine but doesn't check if the account is verified)
<?php
class Login extends Dbh{
protected function getUser($uid, $pwd){
$stmt = $this->connect()->prepare('SELECT users_pwd FROM users WHERE users_uid = ? OR users_email = ?;');
if(!$stmt->execute(array($uid, $pwd))){
$stmt = null;
header("location: ../LoginPage.php?error=stmtfailed");
exit();
}
if($stmt->rowCount()==0){
$stmt = null;
header("location: ../LoginPage.php?error=usernotfound");
exit();
}
$pwdHashed = $stmt->fetchAll(PDO::FETCH_ASSOC);
$checkPwd = password_verify($pwd,$pwdHashed[0]["users_pwd"]);
if($checkPwd ==false){
$stmt = null;
header("location: ../LoginPage.php?error=wrongpassword");
exit();
}
elseif($checkPwd == true){
$stmt = $this->connect()->prepare('SELECT * FROM users WHERE users_uid = ? OR users_email = ? AND users_pwd = ?;');
//HERE IS WHERE I WANT TO IMPLEMENT THE CODE WRITTEN ABOVE BUT IN A WORKING VERSION
//HERE IS WHERE I WANT TO IMPLEMENT THE CODE WRITTEN ABOVE BUT IN A WORKING VERSION
//HERE IS WHERE I WANT TO IMPLEMENT THE CODE WRITTEN ABOVE BUT IN A WORKING VERSION
if(!$stmt->execute(array($uid, $uid, $pwd))){
$stmt = null;
header("location: ../LoginPage.php?error=stmtfailed");
exit();
}
}
if($stmt->rowCount()==0){
$stmt = null;
header("location: ../LoginPage.php?error=usernotfound");
exit();
}
$user = $stmt->fetchAll(PDO::FETCH_ASSOC);
session_start();
$_SESSION["userid"] = $user[0]["users_id"];
$_SESSION["useruid"] = $user[0]["users_uid"];
$stmt = null;
}
}
In conclusion, I want to check whether or not the "Verfication"-value is 1 or 0 in my database.
You may change password check
from
$stmt = $this->connect()->prepare('SELECT users_pwd FROM users WHERE users_uid = ? OR users_email = ?;');
...
$pwdHashed = $stmt->fetchAll(PDO::FETCH_ASSOC);
$checkPwd = password_verify($pwd,$pwdHashed[0]["users_pwd"]);
if($checkPwd ==false){
$stmt = null;
header("location: ../LoginPage.php?error=wrongpassword");
exit();
}
to
$stmt = $this->connect()->prepare('SELECT users_pwd, verification FROM users WHERE users_uid = ? OR users_email = ?;');
...
$dbData = $stmt->fetchAll(PDO::FETCH_ASSOC);
$verification = $dbData[0]["verification"]
$checkPwd = password_verify($pwd,$dbData[0]["users_pwd"]);
if($checkPwd === false || $verification !== 1){
$stmt = null;
if($checkPwd === false) {
header("location: ../LoginPage.php?error=wrongpassword");
} else {
header("location: ../LoginPage.php?error=notverified");
}
exit();
}
That will check password and verification status.
Related
Hello I have been encountering this bug for a long time.
So basically here is by code:
function loginUser($conn, $username, $password) {
$checkExists = checkExists($conn, $username, $username);
if ($checkExists === false) {
header("Location: ../login.php?error=wronglogininfo");
exit();
}
$passwordHashed = $checkExists['password'];
$checkPassword = password_verify($password, $passwordHashed);
if ($checkPassword === false) {
header("Location: ../login.php?error=wronglogin");
exit();
} elseif ($checkPassword === true) {
$query = "SELECT * FROM users WHERE username='$username' AND password='$checkPassword'";
$query_run = mysqli_query($conn, $query);
$usertypes = mysqli_fetch_array($query_run);
if ($usertypes['usertype'] == "admin") {
header('Location: ../login.php?admin');
} elseif ($usertypes['usertype'] == "user") {
header('Location: ../login.php?user');
}
}
}
function checkExists($conn, $username, $email) {
$sql = "SELECT * FROM users WHERE username = ? OR email = ?;";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../register.php?error=stmtfailed");
exit();
}
mysqli_stmt_bind_param($stmt, "ss", $username, $email);
mysqli_stmt_execute($stmt);
$resultData = mysqli_stmt_get_result($stmt);
if ($row = mysqli_fetch_assoc($resultData)) {
return $row;
} else {
$result = false;
return $result;
}
mysqli_stmt_close($stmt);
}
And so the errors work fine.
The real problem is that whenever I login with correct credentials it sends me to a 404 page with a directory I never put. I want it to send be to the admin panel or user page. Can anyone help?
This select looks like a road to ruin: SELECT * FROM users WHERE
username='$username' AND password='$checkPassword' If $checkPassword
is the result of a password_verify(). (Also be careful about possible
SQL injection.)
I suspect this is your main issue. This would essentially translate your query to:
SELECT * FROM users WHERE username = 'tony' AND password = '1';
This will likely return an empty result set, but your very next if statement is expecting a user array populated with data.
if ($usertypes['usertype'] == "admin") {
header('Location: ../login.php?admin');
} elseif ($usertypes['usertype'] == "user") {
header('Location: ../login.php?user');
}
What happens now? You won't be redirected anywhere and the current script will continue processing. So what can you do?
If you already have the user row, via checkExists() (could this be
named better?), why do another call to the database to get the
usertype?
You already have access to your user array because you called checkExists above and verified it is not false. Just use the array directly.
I just cleaned up your code a bit and added in some comments. I did not alter your queries in any way and didn't verify they are correct.
function loginUser($conn, $username, $password) {
// Renamed this variable
// Validate it and use this variable for the remainder of the function.
$user = checkExists($conn, $username, $username);
if ($user === false) {
header("Location: ../login.php?error=wronglogininfo");
exit();
}
$passwordHashed = $user['password'];
// Renamed this variable.
$validPassword = password_verify($password, $passwordHashed);
if ($validPassword === false) {
header("Location: ../login.php?error=wronglogin");
exit();
}
// You now know you have a user and a valid password.
// No need to select them again
if ($user['usertype'] == "admin") {
header('Location: ../login.php?admin');
exit;
}
if ($user['usertype'] == "user") {
header('Location: ../login.php?user');
exit;
}
// What happens if `usertype` not matched? You still need to handle this case?
}
function checkExists($conn, $username, $email) {
$sql = "SELECT * FROM users WHERE username = ? OR email = ?;";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
header("Location: ../register.php?error=stmtfailed");
exit();
}
mysqli_stmt_bind_param($stmt, "ss", $username, $email);
mysqli_stmt_execute($stmt);
$resultData = mysqli_stmt_get_result($stmt);
// Cleaned up this if statement
if ($row = mysqli_fetch_assoc($resultData)) {
return $row;
}
return false;
}
I am doing an android project and I've got a problem while logging into the account. I am able to login even if the password is incorrect or empty. I am unable to recognize the error. I have checked my code but nothing helped me Could anyone help me with this?
My Code:
userLogin.php
require_once '../includes/DbOperations.php';
$response = array();
if($_SERVER['REQUEST_METHOD']=='POST'){
if(isset($_POST['username']) and isset($_POST['password'])){
$db = new DbOperations();
$result = $db->userLogin($_POST['username'], $_POST['password']);
if ($result == 1) {
# code...
$user = $db->getUserByUsername($_POST['username']);
$response['error'] = false;
$response['id'] = $user['id'];
$response['email'] = $user['email'];
$response['username'] = $user['username'];
$response['phone'] = $user['phone'];
$response['gender'] = $user['gender'];
$response['message'] = "Found successfully";
}
elseif ($result == 2) {
# code...
$response['error'] = true;
$response['message'] = "Some error occurred please try again";
}
}else{
$response['error'] = true;
$response['message'] = "Required fields are missing";
}
}
echo json_encode($response);
DbOperations.php
public function userLogin($username, $pass){
$password = md5($pass);
$stmt = $this->con->prepare("SELECT * FROM users WHERE username = ? AND password = ?;");
if($stmt != FALSE){
$stmt->bind_param("ss",$username,$password);
if($stmt->execute()){
return 1;
}else{
return 2;
}
$stmt->store_result();
$stmt->close();
else
{
var_dump($this->con->error);
}
}
public function getUserByUsername($username){
$stmt = $this->con->prepare("SELECT * FROM users WHERE username = ?;");
if($stmt != FALSE){
$stmt->bind_param("s",$username);
$stmt->execute();
return $stmt->get_result()->fetch_assoc();
}
else
{
var_dump($this->con->error);
}
}
please return the value if records found but you are returning the value if query executed successfully.
Your code :
if($stmt->execute()){
return 1;
}else{
return 2;
}
Should be :
if($stmt->num_rows > 0){
return 1;
}else{
return 2;
}
And as per your code if you enter wrong username than it should work to.
if($stmt->execute() != FALSE) is not correct. see below code:
public function userLogin($username, $pass){
$password = md5($pass);
$stmt = $this->con->prepare("SELECT * FROM users WHERE username = ? AND password = ?;");
if($stmt != FALSE){
$stmt->bind_param("ss",$username,$password);
$stmt->execute()
$stmt->store_result();
$rows = $stmt->num_rows;
$stmt->close();
return $rows;
else
{
var_dump($this->con->error);
}
}
public function getUserByUsername($username){
$stmt = $this->con->prepare("SELECT * FROM users WHERE username = ?;");
if($stmt != FALSE){
$stmt->bind_param("s",$username);
$stmt->execute();
return $stmt->get_result()->fetch_assoc();
}
else
{
var_dump($this->con->error);
}
}
i'm having a problem with my sessions, i have a functionality in my application wich requires two different type of users logging in, one is the Admin, with that means he can do everything possible within the application, and other is the Editor, and he can only do a couple of things in it.
My problem is that the sessions seem to be overlaping one another, i login in the admin and the session info is the one from the Editor.
Heres my login from the Admin:
<!---Login PHP--->
<?php
if( isset($_POST['btn-login']) ) {
$email = $_POST['email'];
$senha = $_POST['senha'];
$Error = false;
if (empty($email)) {
$Error= true;
$error = "Preencha o email.";
}
if (empty($senha)) {
$Error = true;
$error2 = "Preencha a senha.";
}
if($email) {
$sql = "SELECT email FROM admin WHERE email = '$email'";
$stmt = $conn->prepare($sql);
$stmt->execute();
$cout = $stmt->rowCount();
//echo "Email - ".$cout;
}
if($senha) {
$sql = "SELECT senha FROM admin WHERE email = '$email'";
$stmt = $conn->prepare($sql);
$stmt->execute();
$cout = $stmt->rowCount();
if($cout == 1) {
//echo "<br>Password - ".$cout;
$hashed = $stmt->fetch(PDO::FETCH_ASSOC);
//echo "<br>Password HASHED - ".$hashed['senha'];
$hashed_pass = $hashed['senha'];
}
}
if (!empty($email) && !empty($senha) && filter_var($email,FILTER_VALIDATE_EMAIL) && password_verify($senha,$hashed_pass) && !$Error) {
$sql = "SELECT email, senha FROM admin WHERE email ='$email' AND senha = '$hashed_pass'";
$query = $conn->prepare($sql);
$query->execute();
$count = $query->rowCount();
if($count == 1){
session_start();
$_SESSION['email'] = $email;
$_SESSION['senha'] = $crypt;
header("Location: home.php");
exit;
}
else {
$error = "Erro: password ou email errados";
}
}
}
?>
Heres my Editor login:
<?php
/*EDITOR*/
if( isset($_POST['btn-login2']) ) {
$email = $_POST['email'];
$senha = $_POST['senha'];
if (empty($email)) {
echo "Preencha o email";
}
if (empty($senha)) {
echo "Preencha a senha";
}
if($email) {
$sql = "SELECT email FROM editor WHERE email = '$email'";
$stmt = $conn->prepare($sql);
$stmt->execute();
$cout = $stmt->rowCount();
//echo "Email - ".$cout;
}
if($senha) {
$sql = "SELECT senha FROM editor WHERE email = '$email'";
$stmt = $conn->prepare($sql);
$stmt->execute();
$cout = $stmt->rowCount();
if($cout == 1) {
//echo "<br>Password - ".$cout;
$hashed = $stmt->fetch(PDO::FETCH_ASSOC);
//echo "<br>Password HASHED - ".$hashed['senha'];
$hashed_pass = $hashed['senha'];
}
}
if (!empty($email) && !empty($senha) && filter_var($email,FILTER_VALIDATE_EMAIL) && password_verify($senha,$hashed_pass)) {
$sql = "SELECT email, senha FROM editor WHERE email ='$email' AND senha = '$hashed_pass'";
$query = $conn->prepare($sql);
$query->execute();
$count = $query->rowCount();
if($count == 1){
session_start();
// criar sessão com o email recebido por post e mandar o utilizador para a página home
$_SESSION['email_e'] = $email;
$_SESSION['senha_e'] = $senha;
header("Location: home.php");
exit;
}
else {
echo "Erro: password ou email errados";
}
}
}
?>
And here is the Sessions file:
<?php
ob_start();
session_start();
// if session is not set this will redirect to login page
if( !isset($_SESSION['email']) && !isset($_SESSION['senha'])) {
header("Location: admin.php");
exit;
}
// ADMIN SESSIONS
if(isset($_SESSION['email'])){
//echo "entrei";
// select loggedin users detail
$res = "SELECT * FROM admin WHERE email='".$_SESSION['email']."'";
$stmt = $conn->prepare($res);
//echo "<br>SQL - > ".$res;
$stmt ->execute();
$count = $stmt ->rowCount();
if ( $count == 1 ) {
$userRow = $stmt->fetch(PDO::FETCH_ASSOC);
}
}
//EDITOR SESSIONS
if(isset($_SESSION['email_e'])) {
//echo "<br>Entrei2";
$sql = "SELECT * FROM editor WHERE email = '".$_SESSION['email_e']."'";
//echo "<br>SQL - > ".$sql;
$stmt = $conn->prepare($sql);
$stmt->execute();
$count = $stmt->rowCount();
if($count == 1) {
$userRow = $stmt->fetch(PDO::FETCH_ASSOC);
}
//echo "<br>Contagem - ".$count;
} else {
echo "<br>Sem Sucesso";
}
?>
And when i was trying to fix this problem i though it might be because i didn't destroy the sessions, but still no fix with that, i'm probably doing something wrong here i believe.
Logout file:
<?php
session_start();
ob_start();
if (!isset($_SESSION['email']) || !isset($_SESSION['email_e'])) {
header("Location: index.php");
exit();
} else if(isset($_SESSION['email'])!="") {
header("Location: index.php");
exit();
}
//ADMIN LOGOUT
if (isset($_GET['logout'])) {
unset($_SESSION['email']);
unset($_SESSION['email_e']);
session_unset();
session_destroy();
header("Location: error.php");
exit;
}
ob_end_flush();
?>
Thanks in advance to anyone who anwsers.
It seems weird to me that you are handling the 2 types of users by creating 2 different session variables. What I believe that is happening is that somehow one of the variables does not get unset, and thus resulting in your problem.
It would be much more simple and elegant to use the same variable ( $_SESSION['email'] ) and then display whatever content you want based on the user type.
Think that you want, at some point, to add a new user type: you would have to edit all the code that handles the login and logout, which is not normal.
Try to only create one login page, for both admins and editors, and get their user type from the database based on their email.
here's my code I use on my local "development" server, but unfortunately my remote server doesn't support mysqli native driver - how is it possible to replace mysqli_stmt_get_result();?
CODE:
$query = "SELECT * FROM class WHERE email = ? AND password = ?";
$stmt = mysqli_prepare($connect,$query);
mysqli_stmt_bind_param($stmt,'ss',$nickname,$password);
mysqli_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$row = mysqli_fetch_assoc($result);
include("year_tester.php");
if(mysqli_num_rows($result) != ""){
$_SESSION['loggedIn'] = true;
$_SESSION['loginName'] = $nickname;
$_SESSION['classIdentify'] = $rocnik.".".$className;
header('Location: index.php');
}
...is it acceptable to rewrite it in PDO? :p
$pdoh=new PDO("mysql:host=127.0.0.1;dbname=testdb;charset=utf8",
$mysqldb_username,$mysqldb_password,
array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
$query = "SELECT * FROM class WHERE email = ? AND password = ?";
//$stmt = mysqli_prepare($connect,$query);
$pdosh=$pdoh->prepare($query);
//mysqli_stmt_bind_param($stmt,'ss',$nickname,$password);
//i feel sorry for the guy writing the garabage collector :(
$pdosh->bindParam(1,$nickname, PDO::PARAM_STR);
$pdosh->bindParam(2,$password, PDO::PARAM_STR);
//mysqli_execute($stmt);
$pdosh->execute(); //using ERRMODE_EXCEPTION right?
//$result = mysqli_stmt_get_result($stmt);
//$row = mysqli_fetch_assoc($result);
$row=$pdosh->fetch();
require("year_tester.php");
if($pdosh->rowCount()>0/*mysqli_num_rows($result) != ""*/){
$_SESSION['loggedIn'] = true;
$_SESSION['loginName'] = $nickname;
$_SESSION['classIdentify'] = $rocnik.".".$className;
header('Location: index.php');
}
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.
I suppose you could modify the query to check $username against both the username AND email fields in the database, e.g. something like
SELECT user_username,user_level
FROM users
WHERE (? IN (user_username, user_email)) AND user_password = ?';
Check for the existence of # and change your query accordingly:
if (strpos($username, '#') === false) {
$nameField = 'user_username';
} else {
$nameField = 'user_email';
}
$sql = 'SELECT user_username,user_level FROM users WHERE '.$nameField.' = ? AND user_password = ?';
The other issue is the salt being based on the username. This will obviously fail if the user decides to switch to the email address. As has been suggested, use a separate salt (unrelated to the username) and add an extra query upfront to retrieve it.
$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)."'
)
";
Just make the query like this. I'd advice using the mysql_real_escape_string as it makes your code better protected against SQL-injection (read-up on that!).
From this point on, you can continue with your code.