简体   繁体   中英

login session destroyed after refresh

I have made a log in script with some Google help but the problem is every time i refresh the page it gets log out and redirect me to the log in page. So basically i want this that a user is logged in after entering his details and not get logged out after a single refresh. my code is:

<?php

if(!isset($_SESSION)){
session_start();
}

$username = mysqli_real_escape_string($con, $_POST['username']);
$password = mysqli_real_escape_string($con, $_POST['password']);

if ($username && $password)

{


$result = mysqli_query($con, "SELECT * FROM admin WHERE username='$username' ");

$numrows = mysqli_num_rows($result);

if($numrows !=0)
{
    while($row = mysqli_fetch_assoc($result))
    {
        $dbusername = $row["username"];
        $dbpassword = $row["password"]; 

    }
        if($username==$dbusername && $password==$dbpassword)
        {

            $_SESSION['username'] = $dbusername;
        }
        else
            echo "Incorrect Password";
}       
else
    header("location: login.php"); 


}
else    
header("location: login.php"); 
?>

mysqli_real_escape_string() REQUIRES you to have an active/established connection to the DB. Since you're doing the m_r_e_s() call BEFORE you connect, you'll simply get back boolean FALSE to signify failure. So you're trashing your "quoted" values.

Boolean false values inserted into a string just get converted into empty strings, so your queries start looking like

SELECT ... WHERE username=''
                           ^---see the boolean false in there?

Your code sequence should be:

session_start();
connect_to_db();
prepare_variables();
do_query();

And since you're using mysqli, why are you manually escaping variables anyways? You could just use a prepared statement + placeholders and bypass the problem entirely.

LEARNING POINT # 1: SESSIONS

Here are some learning points for you in regards to sessions and how to use them efficient and effectively. Please note the problem with your code is you are asking if a session was set before calling session start, so the superglobal $_SESSION is not available and therefore your logical statement always returns false, except for when you call session start in login, where you should never call session start anyway. Call session start 1 time in a config file(make sure you include this file in all of your "views/pages" then you can check if a session is set as normal. read this code very carefully and attempt to understand everything it is doing so that you can take advantage of the power that php's sessions offer.

add to login.php

//upon successful validation of login.
//create an object to store basic user information in. 

$user = (object) ['username'=>$username,'hash_password'=>$password,'group'=>$usergroup,'site_secret'=>$secret];//your user object

$_SESSION['user'] = $user;//store the object in the users session.

add to your config.php or any file that is included in all pages

GLOBAL const static $secret = (string)'someUltraSecretStringThatIsDifficultToGuess';//your site wide secret.(you should probably add this to your config file instead of the login.
session_start(); 

//you have to call session start or you don't have access to $_SESSION superglobal, 
//regardless of a user being logged in or logged out they have a session.
//as a programmer it is your job to figure out how to store data in the session

if(isset($_SESSION['user']) && is_object($_SESSION['user']) && $_SESSION['user']->site_secret == $secret)
{
    $loggedInUser = $_SESSION['user'];//if an authenticaed user session is set and is an object and contains our site secret, we assign the $loggedInUser variable to it. so we can call this variable instead of calling the session ad nauseum in our code.
}

now in your files to test if a user is loggedIn

if($loggedInUser !== null && is_object($loggedInUser) && $loggedInUser->site_secret = $secret)
{
    //user is logged in. no reason to even call the database at this point, unless there is extra information you need.
    //if said information is going to be accessed on multiple pages, its probably wise to include it in the object when you create it during the login process. don't store overly sensitive
    //information in the object in any circumstance. things like credit card numbers, plain text passwords, security questions are big no nos.
}

now if you need to call this object from inside the function there are two ways

//pass by reference

function foo($loggedInUser) 
{
    //your object is available here because you passed by reference! 
    //you can check if a user is loggedIn from within functions now without a single call to the database!
}

//pass with global language feature.
function bar()
{
    global $loggedInUser; //object is available here through usage of global directive. nifty eh?
}

other considerations

consider adding a sitewide secret property to your loggedInUser object and check for the presence of this secret to identify a valid session. it is possible to create a variable called $loggedInUser if a user isn't logged in by passing a malformed get request. odds are that the attacker won't be able to guess your site secret though. an example of this sitewide secret is shown in the first example.

LEARNING POINT # 2: A crash course to Object Oriented Mysqli

creating the connection object.

$mysqli = new mysqli("db-host","db-username","db-password","db-name");

setting the charset

//since your object is already created, you can now set a property on the object

$mysqli->set_charset("utf8");//set it to whatever the collation of your database is.

//side note: you should user utf_unicode_ci in your database and utf8 in php.

running a query

$query = $mysqli->query("SELECT column1,column2,column3 FROM table1 WHERE 1 LIMIT 30");

//getting number of rows
$num_rows = $query->num_rows;//your mysqli object has morphed into $query at this point.

//working with the result set
if($num_rows > 0)
{
    while($row = $query->fetch_assoc())
    {
    echo '<li>'.$row["column1"].' | '.$row["column2"].' | '.$row["column3"].'</li>';
    }
    $query->close();//optionally close the query object NOTE: the $mysqli object is still open
    $query->free();//optionally free the result set
}
//when you are done with your $mysqli object close the connection
$mysqli->close();

prepared statements: an alternative to escaping values manually

$stmt = $mysqli->prepare("SELECT column1,column2,column3 FROM table1 WHERE column4 = ? column5 = ? and column6 = ?");//prepare our query.

//now we need to assign our variables to the question marks in the statement above in the correct order.
// s represents string, d represents double and i represents an integer.
$stmt->bind_param('sdi',$column4,$column5,$column6);//for illustrative purposes i name the variables the same as the column they correspond to so you can understand.

//now that we have bound our parameters to our statement wehave to execute it. if it doens't execute there is an error in our query or binding parameters

if($stmt->execute())
{
    //now we have two ways we can work with this result set. i am only going to show you what i consider the best way, `bind_result().
    $stmt->bind_result($column1,$column2,$column3);//binds in the same order of our columns.
    if($stmt->num_rows > 0) {
        //great, our query returned a result! lets work with this data now
        while($stmt->fetch())
        {
            echo '<li>'.$column1.' | '.$column2.' | '.$column3.'</li>';//we prent each row of our result. easy peasy
        }
        $stmt->close();//no need to free the result, as it is not stored by default.
    }
    //if there were no results, no need to close stmt as it was automatically closed by default.    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM