I am writing some session handling code that will use a mysql database. I've read up on session_set_save_handler() pretty extensively:
http://us2.php.net/manual/en/function.session-set-save-handler.php
but it doesn't describe the various functions in much detail at all or exactly when they get called:
open
close
read
write
destroy
gc
even so, i have a fair inkling of how things work, but the issue i'm facing now is that i want to use my own function to determine the session ids. if someone makes up some session id and attempts to start a session with it, i want to toss their session id and make one for them myself rather than creating an empty session with their chosen session id--this is in order to protect against 'session fixation'.
QUESTIONs:
1) can any of these function(s) determine the session id to be used for a new session?
2) is there any way to re-write session_regenerate_id() so that i can determine how new session ids are generated? I have tried in the sample class i wrote below.
3) If my 'read' function is presented with an id for which no session exists, can I call session_id() with a new id of my own choosing to dump the bogus/invalid session id?
4) is the call to register_shutdown_function necessary or not? I've seen it in other people's samples but don't know what it's doing.
Here's a sample of what i'm trying:
<?php
class session_class {
function session_class() {
session_set_save_handler(
array(&$this, '_open'),
array(&$this, '_close'),
array(&$this, '_read'),
array(&$this, '_write'),
array(&$this, '_destroy'),
array(&$this, '_gc')
);
// is this necessary?
register_shutdown_function('session_write_close');
session_start();
} // session_class()
function new_id() {
return md5("random data seed goes here");
} // new_id()
function regenerate_id() {
// saves the current session id as old
$old_id = session_id();
// WILL THIS WORK? WILL ALL DATA GET LOST?
$new_id = $this->new_id();
session_id($new_id);
// IS THIS STRICTLY NECESSARy? OR WILL IT JUST CAUSE PERFORMANCE PROBLEMS?
$this->_destroy($old_id);
}
// WHEN IS THIS RUN?? WHAT DOES IT DO??
function _open($save_path, $session_name) {
// what does this do?
return true;
} // _open()
// WHEN IS THIS RUN?? WHAT DOES IT DO?
function _close() {
return true;
} // _close()
function _read($id) {
$now = time();
$sql = "SELECT data FROM sessions
WHERE id='" . mysql_escape_string($id) . "'
AND (last_access_time+" . SESSION_TIMEOUT . ") < " . $now;
$result = mysql_query($sql)
or die('Session read db query failed.');
if (mysql_num_rows($result) > 0) {
$row = mysql_fetch_assoc($result)
or die('Session read query failed to fetch anything.');
return $row['data'];
}
// if anything goes wrong, apparently we MUST return an empty string
// WHY IS THIS??
return '';
} // _read()
function _write($id, $data) {
$now = time();
$sql = "REPLACE
INTO sessions
VALUES ('" . mysql_escape_string($id) . "', '$now', '" . mysql_escape_string($data) . "')";
return mysql_query($sql);
} // _write
function _destroy($id) {
$sql = "DELETE
FROM sessions
WHERE id = '" mysql_real_escape_string($id) . "'";
return mysql_query($sql);
}
function _gc($max) {
$old = time() - $max;
$old = mysql_real_escape_string($old);
$sql = "DELETE
FROM sessions
WHERE access < '$old'";
return mysql_query($sql);
} // _gc()
} // class session_class
?>