开发者

session_set_save_handler causing login loop

开发者 https://www.devze.com 2023-03-14 17:46 出处:网络
I\'m trying to write sessions to database using session_set_save_handler(). I\'m getting an infinite loop, where my system wants to log me in, but cannot find the session, so it logs me out... but the

I'm trying to write sessions to database using session_set_save_handler(). I'm getting an infinite loop, where my system wants to log me in, but cannot find the session, so it logs me out... but the session exists apparently - just not in the table.

Anyway, here's my code for the session functions - I don't think there's anything wrong here:

<?php

// session.functions.php

$db = new mysqli("127.0.0.1", "user", "pass", "db");
// define 'openSession()' function
function openSession($sessionPath, $sessionName) {
    return true;
}

// define 'closeSession()' function
function closeSession() {
    return true;
}

// define 'readSession()' method
function readSession($sessionId) {
    global $db;
    // escape session ID
        $sessionId = $db->real_escape_string($sessionId);
    $result = $db->query("SELECT sessiondata FROM sessions WHERE
sessionid='$sessionId' AND expiry > NOW()");
    if ($result->num_rows > 0) {
        $row = $result->fetchRow();
        return $row['sessiondata'];
    }
    // return empty string
    return "";
}

// define 'writeSession()' function
function writeSession($sessionId, $sessionData) {
    global $db;
    $expiry = time() + get_cfg_var('session.gc_maxlifetime') - 1;
    // escape session ID & session data
        $sessionId = $db->real_escape_string($sessionId);
        $sessionData = $db->real_escape_string($sessionData);
    $result = $db->query("SELECT sessionid FROM sessions WHERE
sessionid='$sessionId'");
    // check if a new session must be stored or an existing one must be updated 
    ($result->num_rows > 0) ? $db->query("UPDATE sessions SET     sessionid='$sessionId',expiry='$expiry',sessiondata=
'$sessionData' WHERE sessionid='$sessionId'") or die(mysqli_error($db)) : $db->query("INSERT INTO sessions (sessionid,expiry,sessiondata) VALUES ('$sessionId','$expiry','$sessionData')") or die(mysqli_error($db));
    return true;
}

// define 'destroySession()' function
function destroySession($sessionId) {
    global $db;
    // escape session ID
        $sessionId = $db->real_escape_string($sessionId);
    $db->query("DELETE FROM sessions WHERE sessionid='$sessionId'");
    return true;
}

// define 'gcSession()' function
function gcSession($maxlifetime) {
    global $db;
    $db->query("DELETE FROM sessions WHERE expiry < NOW()");
    return true;
}

?>

This is the session setting for login:

$this->set_session(array_merge($rs->fetch_assoc(), array('expires' => time() + (15 * 60))));

set by function:

private function set_session($a=false) {
    if (!empty($a)) {
        $_SESSION['exp_user'] = $a;
    }
}

How does my login system check to see if I'm already logged in?

public function check_status() {
    if (empty($_SESSION['exp_user']) || @$_SESSION['exp_user']['expires'] < time()) {
        return false;
    } else {
        return true;
    }
}

Turns out, the value of $_SESSION, according to var_dump is array(0) { }

and the check in the web application itself:

// This is in authorisation.php

if(empty($_SESSION['exp_user']) || @开发者_如何转开发$_SESSION['exp_user']['expires'] < time()) {
        header("location:/login.php");  //@ redirect 
} else {
    $_SESSION['exp_user']['expires'] = time()+(15*60);  //@ renew 15 minutes
        //echo $SID = session_id();
}

Now, this is what I have in that index.php file at the top:

require('includes/session.functions.php');
session_set_save_handler('openSession', 'closeSession', 'readSession', 'writeSession', 'destroySession', 'gcSession');
session_start();
include('includes/authorisation.php');

Here's the database:

session_set_save_handler causing login loop

If I comment out session_set_save_handler(), we don't get the loop, however, if I keep it there in action, I get the loop between index and the login system (already logged in -> index ::check login loop.)

print_r(session_set_save_handler('openSession', 'closeSession', 'readSession', 'writeSession', 'destroySession', 'gcSession')); == 1 

var_dump(session_set_save_handler('openSession', 'closeSession', 'readSession', 'writeSession', 'destroySession', 'gcSession')); == bool(true)

Any ideas what I'm doing wrong?


It seems you are mixing up two different time formats. In mysql, NOW() gives you a time in the format:

Returns the current date and time as a value in 'YYYY-MM-DD HH:MM:SS' or YYYYMMDDHHMMSS.uuuuuu format, depending on whether the function is used in a string or numeric context.

In php, time() gives you:

Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).

In your sql statements you are comparing the two and you can´t as they are completely different formats.


It turns out that there was an extra session_start(), which would reset the session.

0

精彩评论

暂无评论...
验证码 换一张
取 消