I have a website that has a membership system. When users log in, I validate username/password from the database and start a session, $_SESSION['userid'] that contains their id (I have not implemented anything using cookies yet)
I have a problem, the system works fine most of the times, but some users have reported that they eventually find themselves logged in to some other random users account. That probably means that $_SESSION['userid'] changes without any reason to something else and I'm pretty sure I'm not doing anything to change it.
Any ideas why this could be happening ?
edit : Summary of what I am doing
This method start the session
function startSession($id){
$_SESSION['logged_in'] = 1;
$_SESSION['userid'] = $id;
}
This method checks login
function isLoggedIn(){
return isset($_SESSION['logged_in']) && isset($_SESSION['userid']) && $_SESSION['userid']!=" " && $_SESSION['logged_in']==1;
}
This is the logout method
function logout(){
$_SESSION['logged_in'] = 0;
$_SESSION['userid'] = 0;
unset($_SESSION['logged_in']);
unset($_SESSION['userid']);
session_destroy();
if (!isLoggedIn()){ return "S3"; }
else { return "E3"; }
}
And this is how I check if the user is logged in most places
if (isLoggedIn()){ $profileid = $_SESSION['userid']; }
This is the login function, this is where I call startSession
function login($username, $password){
$pdo = newPDO();
$username = sanitize_string($username);
$password = sha1(sanitize_string($password));
$query = $pdo->prepare("SELECT id FROM ".TABLE_PROFILE." WHERE nick=:nick AND pass=:pass LIMIT 1");
$query->execute(array(':nick'=>$username, ':pass'=>$password));
$result = $query->fetch(PDO::FETCH_ASSOC);
if (count($result['id']) == 1){
startSession($result['id']);
loginExecution();
return "S1";
}
else{ return "E1"; }
}
The problem is in your login function
Your script is not checking username and password for any data, and if the username and password is empty or incorrect, your client will gets the firs available id from database.
function login($username, $password){
$pdo = newPDO();
$username = sanitize_string($username);
$password = sanitize_string($password);
// Check data for existing
if (empty($username)) throw new Exeption('Empty username');
if (empty($password)) throw new Exeption('Empty password');
$password = sha1($password);
$query = $pdo->prepare("SELECT id FROM ".TABLE_PROFILE." WHERE nick=:nick AND pass=:pass LIMIT 1");
$query->execute(array(':nick'=>$username, ':pass'=>$password));
$result = $query->fetch(PDO::FETCH_ASSOC);
if (count($result['id']) == 1){
startSession($result['id']);
loginExecution();
return "S1";
}
else{ return "E1"; }
}
P.s. Always check incoming data, before SQL queries
Realistically the only thing I can think of that would cause this is something setting $_SESSION['userid'] to another members id. Assuming this is what you are using to check which members information to show. Are you perhaps doing something if the $_SESSION['userid'] variable is not set that may end up setting $_SESSION['userid'] incorrectly? i.e. if their php session is reset.
Related
So I am making a simple login page in PHP. I have 2 tables, one for Staff (admin, manager, etc...) and one for Customer, both have 3 columns in common: username, password, role. When the user login, role will be set in session to redirect the user to the appropriate page. Currently my code is as below:
function.php
function queryMySQL($query)
{
global $conn;
$result = $conn->query($query);
if(!$result)
{
die($conn->error);
}
return $result;
}
function passwordToToken($password)
{
global $salt1;
global $salt2;
$token = hash("ripemd128", "$salt1$password$salt2");
return $token;
}
login.php
<?php
require_once 'function.php'
$user = $_POST['user'];
$pass = $_POST['pass'];
$token = passwordToToken($pass); //encrypt password
$query = "Select userId, username, password, role
from users
where username = '$user'
and password = '$token'
union
Select customerId, username, password, role
from customer
where username = '$user'
and password = '$token'";
$result = queryMySQL($query); //function return mysqli_query
if($result->num_rows == 0)
{
$error = "Username/password is invalid";
echo $error;
} else {
session_start();
$_SESSION['uId'] = mysqli_fetch_array($result)[0];
$_SESSION['user'] = $user;
$_SESSION['pass'] = $pass;
$role = mysqli_fetch_array($result)[3];
if($role != 'admin' || $role != 'staff' || $role != 'manager')
{
$_SESSION['role'] = 'customer';
} else {
$_SESSION['role'] = $role;
}
echo $role;
}
?>
My problem is that when the user login correctly, the $role variable is blank, however if I echo the $_SESSION['uId'] it does return result (the userID), and even if I change the $_SESSION['uId'] value to mysqli_fetch_array($result)[3] I still get the correct result when echo (the user role).
Your problem is that you keep trying to fetch more results. Each time you call mysqli_fetch_array() you ask for the next row - but you only expect one.
Instead, assign the row to a variable $row and use that where you need the columns.
Also, I've changed your role-checks to simplify it a bit. Your current logic was slightly incorrect, as it would always be a customer.
session_start();
$row = mysqli_fetch_array($result);
$_SESSION['uId'] = $row[0];
$_SESSION['user'] = $user;
$_SESSION['pass'] = $pass;
$role = $row[3];
if (!in_array($role, ['admin', 'staff', 'manager']))
{
$_SESSION['role'] = 'customer';
} else {
$_SESSION['role'] = $role;
}
echo $role;
That said, you probably can alter your approach to have one table users, and a column to indicate what role they have. No need to have separate tables.
You should also use a prepared statement, and proper hash of your passwords. See How to use password_hash and How can I prevent SQL injection in PHP?
Propably just one row is returned from query and you are calling mysqli_fetch_array twice so the second call returns null.
BTW shouldn't that be if($role != 'admin' && $role != 'staff' && $role != 'manager')?
<?php
if(isset($_POST['submit'])) {
$UserName = mysql_real_escape_string($_POST['UserName']);
$password = mysql_real_escape_string($_POST['password']);
$checkbox = isset($_POST['remember_me']);
if(user_exists ($UserName, $db_connect)) {
$result = mysqli_query ($db_connect, "SELECT password FROM users WHERE UserName = '$UserName'");
$retrievepassword = mysqli_fetch_assoc($result);
if(md5($password) !== $retrievepassword['password']) {
$alert = "Invalid Password";
} else {
$_SESSION['UserName'] = $UserName;
if($checkbox == "on") {
setcookie("UserName", $UserName, time()+3600);
}
header("location: profile.php");
}
} else {
$alert = "Username doesn't exit in database";
}
}
?>
I've made the following login script which is working fine and now I want to check the user's status before login, if user is active, it will login and if it's request is pending or rejected, it will display an error.
I've done the 1st part and confused about the other part where I've to check for the status.
Can anybody help me according to my code?
I am assuming that you have a column in your DB that stores the user's status.
Sooo .. The answer to your question is, after checking if the username is existing in you DB, check if the status is "active" or not. If no, then just display the error message.
You may think of another way to query your data, like:
SELECT * FROM USERS WHERE USERNAME = 'username' AND PASSWORD = 'password' AND STATUS = true
So that you can determine right away if it is active or not if it does not return anything.
I hope this helps. :)
You can check status after checking valid password and return appropriate message. Try below code :
if(user_exists ($UserName, $db_connect))
{
$result = mysqli_query ($db_connect, "SELECT password,status FROM users WHERE
name = '$UserName'");
$retrievepassword = mysqli_fetch_assoc($result);
if(md5($password) !== $retrievepassword['password'])
{
$alert = "Invalid Password";
}
else
{
//check Status
if($retrievepassword['status'] == 1) //whatever condtion to match
{
$_SESSION['UserName'] = $UserName;
if($checkbox == "on")
{
setcookie("UserName", $UserName, time()+3600);
}
header("location: profile.php");
}
else
{
$alert = "User Not active"; //Message to display
}
}
}
else
{
$alert = "Username doesn't exit in database";
}
There are two ways :
Either add condition in your where to check whether user is active
or not.
Or, once you validated user for correct user/password, then
validate through if condition and navigate to correct page
accordingly.
Also, correct your SQL to use prepared statement.
$stmt = $dbConnection->prepare('SELECT * FROM users WHERE
UserName = ? AND password = ?');
$stmt->bind_param('s', $UserName);
$stmt->bind_param('s', md5($password));
$stmt->execute();
First of all, I would like to point out that you have used $ _SESSION without starting the session. To do this you have to write
session_start();
at the beginning of the code.
To verify that the user is logged in, write this just under session_start():
if(isset($_SESSION['UserName']) or isset($_COOKIE['UserName'])){
header("location: profile.php");
}
If you do not know how to check in profile.php if the user is logging in here is how to do it:
PS: I suggest you create a check.php file so that you just include it in the pages reserved for logged in users.
check.php
if(!isset($_SESSION['UserName']) or !isset($_COOKIE['UserName'])){
// Redirect to login or enter what you want to happen if the user is not logged in
}
The problem with my simple login system is that it only accepts access from the first item in the database, which is "user1". When I tried to login the second user, which is "user2", it says incorrect though the username and password combination was actually correct. Can someone help me figure out what's wrong with my code?
<?php
session_start();
$pdo = new PDO('mysql:host=127.0.0.1;dbname=sample', 'root', '');
if(isset($_POST['username'], $_POST['password'])) {
$username = $_POST['username'];
$password = $_POST['password'];
$query = $pdo->query("SELECT * FROM users");
while($row = $query->fetch(PDO::FETCH_OBJ)) {
if($username == $row->username && $password == $row->password) {
$_SESSION['username'] = $username;
header('Location: success.php');
exit();
} else {
die('Incorrect username and password combination');
}
}
}
if(isset($_SESSION['username'])) {
header('Location: success.php');
exit();
}
?>
Description
Actually the problem is in your Logic and which is of using die() and exit() function. Look at your code the first iteration of while will not match with your user2 and the code will die(). The die() function ends all the flow of code hence every time you set username to user2 and run you will get the same result. Try to use die() or exit() function after the While Loop so the code moves to next iteration if not match on the first iteration.
Explnation
Moreover apply username and password by using where clause in query it will provide more benefits to you.
It will Minimize your code
By this logic which you are using at the moment, if your USER data increases
it will increase your process time of LOGIN because it will first fetch all the rows from USER table then iterate over it un-till it finds the match against username.
But if you still want to continue with this approach you may use as following
Code
session_start();
$pdo = new PDO('mysql:host=127.0.0.1;dbname=sample', 'root', '');
if (isset($_SESSION['username'])) {
//if session is already set navigate to success.php
header('Location: success.php');
} else {
//else if session is not set
//authenticate the user first
if (isset($_POST['username'], $_POST['password'])) {
$username = $_POST['username'];
$password = $_POST['password'];
$query = $pdo->query("SELECT * FROM users");
while ($row = $query->fetch(PDO::FETCH_OBJ)) {
if ($username == $row->username && $password == $row->password) {
$_SESSION['username'] = $username;
header('Location: success.php');
exit();
}
}
return 'Incorrect username and password combination';
} else {
return 'username and password required';
}
}
I've been trying to create a login for my project, but i don't know what i'm doing wrong.
This is what i use to check if the button is pressed:
if(isset($_POST['login'])){
//Get Vars
$username = $_POST['username'];
$password = md5($_POST['password']);
if(login($username, $password)){
echo 'You have been logged in';
} else {
echo 'Wrong username and password';
}
}
This is my login function:
function login($username, $password){
$db = new Database();
$query=("SELECT * FROM user
WHERE username = $username
AND password = $password");
//Bind Values
$row = $db->select($query);
-----------------------------------------
$count = mysqli_num_rows($row);
//Check Rows
if($count == 1){
setUserData($row);
return true;
} else {
return false;
}
-------------------------------------
I BELIEVE THIS IS THE PART OF THE ERROR
}
And here is my setUserData function:
function setUserData($row){
$_SESSION['is_logged_in'] = true;
$_SESSION['user_id'] = $row['id'];
$_SESSION['username'] = $row['id'];
$_SESSION['name'] = $row['name'];
}
I don't know if i need to start a session for this, and if i need to, where do i put the code.
Also how can i initialize it in the code to check, lets say, if $count works, because when i simply type echo $count, it just says Unidentified variable : count
For education purposes, I will list a referente to rewrite your code:
Sanitize $_POST with filter_input
Store pass as md5 hash it's a security flaw
See session_start and session_regenerate_id
Prefer to use PDO against direct mysql native functions
Well i found my error, its was the form that was making the problems, i forgot to put in method="POST" and action="login.php".
Silly me. Thank you all for helping me.
I guess your query should be:
$query=("SELECT * FROM user
WHERE username = '$username'
AND password = '$password'");
For some reason inputs in my login page don't seem to be getting processes correctly. Correct user inputs are getting returned as invalid (wrong password) having had a look through, I can't see anything particularly obvious. But I can only assume the username or password isn't getting passed for some reason. Would someone more experienced be able to take a look and suggest how I can put it right. Thanks guys. P.S My form is OK, so not included.
function logcon($user, $password )
{
$user = mysqli_real_escape_string($this->conn, $user);
$esc_password = mysqli_real_escape_string($this->conn,$password);
$sql = "SELECT * from USERS WHERE username ='{$user}' AND password='{$password}'";
$result = mysqli_query($this->conn, $sql);
$row = mysqli_fetch_array($result);
return $row;
}
Login page.
if(isset($_POST['submit'])){
$user=$_POST['user'];
$password=$_POST['password'];
//To ensure that none of the fields are blank when submitting the form if
if(isset($_POST['user']) && isset($_POST['password']))
{
$user = stripslashes($user);
$password = stripslashes($password);
$db1=new dbmember();
$db1->openDB();
$row=$db1->logcon($user, $password);
if($row[0]==1)
{
session_start();
$_SESSION['user'] = $user;
$_SESSION['password'] = $password;
$_SESSION['loggedin'] = "true";
header("location:index.php");
}
else
{
print ('<div id="error">Acess denied, wrong username or password?</div>');
}
}
else
{
print ('<div id="error">Enter something!</div>');
}
}
It appears you are using the wrong variable name in your query. I would also suggest you look into doing some sort of hashing and salting of your passwords instead of saving them as plain text.
$sql = "SELECT * from USERS WHERE username ='{$user}' AND password='{$password}'";
should be
$sql = "SELECT * from USERS WHERE username ='{$user}' AND password='{$esc_password}'";
And your conditional check seems off, you are checking to see if the first field in the results is = 1 instead of seeing if there is a return.
if($row[0]==1)
Should probably be
if($row)