I have a site that has always worked fine for most users but now i'm having problems with certain users getting logged out. I'm not certain, but in some cases at least they are behind a proxy.
My site uses phpBB's login code which performs a check against a portion of the user's ip address. I'm not sure if that's the issue...it could be something else relating to cookies and proxies. I know so little about proxies.
Anyway, the phpbb session-related code does the following:
1) gets user IP and encodes it thusly:
function encode_ip($dotquad_ip)
{
$ip_sep = explode('.', $dotquad_ip);
return sprintf('%02x%02x%02x%02x', $ip_sep[0], $ip_sep[1], $ip_sep[2], $ip_sep[3]);
}
$client_ip = ( !empty($HTTP_SERVER_VARS['REMOTE_ADDR']) )
? $HTTP_SERVER_VARS['REMOTE_ADDR']
:( ( !empty($HTTP_ENV_VARS['REMOTE_ADDR']) )
? $HTTP_ENV_VARS['REMOTE_ADDR']
: getenv('REMOTE_ADDR') );
$user_ip = encode_ip($client_ip);
2) user-related and session info is stored in a variable called $userdata by making this call:
// $user_ip from above, PAGE_INDEX is just whatever page you are on
$userdata = session_pagestart($user_ip, PAGE_INDEX);
here is session_pagestart()
function session_pagestart($user_ip, $thispage_id)
{
global $db, $lang, $board_config;
global $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $SID;
$cookiename = $board_config['cookie_name'];
$cookiepath = $board_config['cookie_path'];
$cookiedomain = $board_config['cookie_domain'];
$cookiesecure = $board_config['cookie_secure'];
$current_time = time();
unset($userdata);
if ( isset($HTTP_COOKIE_VARS[$cookiename . '_sid']) || isset($HTTP_COOKIE_VARS[$cookiename . '_data']) )
{
$sessiondata = isset( $HTTP_COOKIE_VARS[$cookiename . '_data'] ) ? unserialize(stripslashes($HTTP_COOKIE_VARS[$cookiename . '_data'])) : array();
$session_id = isset( $HTTP_COOKIE_VARS[$cookiename . '_sid'] ) ? $HTTP_COOKIE_VARS[$cookiename . '_sid'] : '';
$sessionmethod = SESSION_METHOD_COOKIE;
}
else
{
$sessiondata = array();
$session_id = ( isset($HTTP_GET_VARS['sid']) ) ? $HTTP_GET_VARS['sid'] : '';
$sessionmethod = SESSION_METHOD_GET;
}
//
if (!preg_match('/^[A-Za-z0-9]*$/', $session_id))
{
$session_id = '';
}
$thispage_id = (int) $thispage_id;
//
// Does a session exist?
//
if ( !empty($session_id) )
{
//
// session_id exists so go ahead and attempt to grab all
// data in preparation
//
$sql = "SELECT u.*, s.*
FROM " . SESSIONS_TABLE . " s, " . USERS_TABLE . " u
WHERE s.session_id = '$session_id'
AND u.user_id = s.session_user_id";
if ( !($result = $db->sql_query($sql)) )
{
message_die(CRITICAL_ERROR, 'Error doing DB query userdata row fetch', '', __LINE__, __FILE__, $sql);
}
$userdata = $db->sql_fetchrow($result);
//
// Did the session exist in the DB?
//
if ( isset($userdata['user_id']) )
{
//
// Do not check IP assuming equivalence, if IPv4 we'll check only first 24
// bits ... I've been told (by vHiker) this should alleviate problems with
// load balanced et al proxies while retaining some reliance on IP security.
//
$ip_check_s = substr($userdata['session_ip'], 0, 6);
$ip_check_u = substr($user_ip, 0, 6);
if ($ip_check_s == $ip_check_u)
{
$SID = ($sessionmethod == SESSION_METHOD_GET || defined('IN_ADMIN')) ? 'sid=' . $session_id : '';
//
// Only update session DB a minute or so after last update
//
if ( $current_time - $userdata['session_time'] > 60 )
{
// A little trick to reset session_admin on session re-usage
$update_admin = (!defined('IN_ADMIN') && $current_time - $userdata['session_time'] > ($board_config['session_length']+60)) ? ', session_admin = 0' : '';
$sql = "UPDATE " . SESSIONS_TABLE . "
SET session_time = $current_time, session_page = $thispage_id$update_admin
WHERE session_id = '" . $userdata['session_id'] . "'";
if ( !$db->sql_query($sql) )
{
message_die(CRITICAL_ERROR, 'Error updating sessions table', '', __LINE__, __FILE__, $sql);
}
if ( $userdata['user_id'] != ANONYMOUS )
{
$sql = "UPDATE " . USERS_TABLE . "
SET user_session_time = $current_time, user_session_page = $thispage_id
WHERE user_id = " . $userdata['user_id'];
if ( !$db->sql_query($sql) )
{
message_die(CRITICAL_ERROR, 'Error updating sessions table', '', __LINE__, __FILE__, $sql);
}
}
//
// Delete expired sessions
//
$expiry_time = $current_time - $board_config['session_length'];
$sql = "DELETE FROM " . SESSIONS_TABLE . "
WHERE session_time < $expiry_time
AND session_id <> '$session_id'";
if ( !$db->sql_query($sql) )
{
message_die(CRITICAL_ERROR, 'Error clearing sessions table', '', __LINE__, __FILE__, $sql);
}
setcookie($cookiename . '_data', serialize($sessiondata), $current_time + 31536000, $cookiepath, $cookiedomain, $cookiesecure);
setcookie($cookiename . '_sid', $session_id, 0, $cookiepath, $cookiedomain, $cookiesecure);
}
return $userdata;
}
}
}
//
// If we reach here then no (valid) session exists. So we'll create a new one,
// using the cookie user_id if available to pull basic user prefs.
//
$user_id = ( isset($sessiondata['userid']) ) ? intval($sessiondata['userid']) : ANONYMOUS;
if ( !($userdata = session_begin($user_id, $user_ip, $thispage_id, TRUE)) )
{
message_die(CRITICAL_ERROR, 'Error creating user session', '', __LINE__, __FILE__, $sql);
}
return $userdata;
}
Don't worry about session_begin...that only gets called when no session is found.
3) lastly, we check to see if someone is logged in thusly:
if ($userdata['session_logged_in']) {
// YES
} else {
// NO
}
might the problem be this part:
$ip_check_s = substr($userdata['session_ip'], 0, 6);
$ip_check_u = substr($user_ip, 0, 6);
if ($ip_check_s == $ip_check_u) {
// RESUME SESSION
}
// otherwise, CREATE NEW SESSION