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:
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.
精彩评论