php - Codeigniter random session logouts (Already tried override session class AND raising session_time_to_update -
i have tried both suggestions at: codeigniter session bugging out ajax calls
but $config['sess_time_to_update'] = php_int_max
still seeing random logouts.
i took suggestions of creating class my_session
user's still reporting random logouts , logs seem indicate this.
edit: here session config:
$config['sess_cookie_name'] = 'phppos'; $config['sess_expiration'] = 86400; $config['sess_expire_on_close'] = true; $config['sess_encrypt_cookie'] = false; $config['sess_use_database'] = true; $config['sess_table_name'] = 'sessions'; $config['sess_match_ip'] = false; $config['sess_match_useragent'] = true; $config['sess_time_to_update'] = php_int_max;
i think you're suffering ajax session race condition. had same problem, , solved overriding ci session class. have article here:
http://www.hiretheworld.com/blog/tech-blog/codeigniter-session-race-conditions
the cleanest thing utilize my_session class, in libraries folder, , override methods written in link above. sorry lack of indentation, :p
class my_session extends ci_session { public function __construct() { parent::__construct(); } /********************************************************************* * overrides codeigniter session library * * handle race status during session_id updates. * - maintain old session id around in case have handle race * conditions. * - changes marked string "old_session_id_changes". * * session table changes: * alter table `sessions` add together column `old_session_id` varchar(40) default null comment 'old session id' after `user_data`, * add together index `old_session_id`(`old_session_id`); * delete `sessions`; *********************************************************************/ /** * fetch current session info if exists * * @return bool */ public function sess_read() { // fetch cookie $session = $this->ci->input->cookie($this->sess_cookie_name); // no cookie? goodbye cruel world!... if ($session === null) { log_message('debug', 'a session cookie not found.'); homecoming false; } // decrypt cookie info if ($this->sess_encrypt_cookie === true) { $session = $this->ci->encrypt->decode($session); } else { // encryption not used, need check md5 hash $hash = substr($session, strlen($session)-32); // lastly 32 chars $session = substr($session, 0, strlen($session)-32); // md5 hash match? prevent manipulation of session info in userspace if ($hash !== md5($session.$this->encryption_key)) { log_message('error', 'the session cookie info did not match expected. possible hacking attempt.'); $this->sess_destroy(); homecoming false; } } // unserialize session array $session = $this->_unserialize($session); // session info unserialized array right format? if ( ! is_array($session) or ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity'])) { $this->sess_destroy(); homecoming false; } // session current? if (($session['last_activity'] + $this->sess_expiration) < $this->now) { $this->sess_destroy(); homecoming false; } // ip match? if ($this->sess_match_ip === true && $session['ip_address'] !== $this->ci->input->ip_address()) { $this->sess_destroy(); homecoming false; } // user agent match? if ($this->sess_match_useragent === true && trim($session['user_agent']) !== trim(substr($this->ci->input->user_agent(), 0, 120))) { $this->sess_destroy(); homecoming false; } // there corresponding session in db? if ($this->sess_use_database === true) { /* * begin old_session_id_changes * * search both session_id , old_session_id fields * incoming session id. * * used be: * $this->ci->db->where('session_id', $session['session_id']); * * manually create or status because causes to the lowest degree * disturbance existing code. * * store session id cookie can see if * came in through old session id later. */ $this->ci->db->where( '(session_id = ' . $this->ci->db->escape($session['session_id']) . ' or old_session_id = ' . $this->ci->db->escape($session['session_id']) . ')' ); $this->cookie_session_id = $session['session_id']; /* * end old_session_id_changes */ if ($this->sess_match_ip === true) { $this->ci->db->where('ip_address', $session['ip_address']); } if ($this->sess_match_useragent === true) { $this->ci->db->where('user_agent', $session['user_agent']); } $query = $this->ci->db->limit(1)->get($this->sess_table_name); // no result? kill it! if ($query->num_rows() === 0) { $this->sess_destroy(); homecoming false; } // there custom data? if so, add together main session array $row = $query->row(); if ( ! empty($row->user_data)) { $custom_data = $this->_unserialize($row->user_data); if (is_array($custom_data)) { foreach ($custom_data $key => $val) { $session[$key] = $val; } } } /* * begin old_session_id_changes * * pull session_id database populate curent * session id because old 1 stale. * * pull old_session_id database can * compare current (cookie) session id against later. */ $session['session_id'] = $row->session_id; $session['old_session_id'] = $row->old_session_id; /* * end old_session_id_changes */ } // session valid! $this->userdata = $session; unset($session); homecoming true; } // -------------------------------------------------------------------- /** * write session info * * @return void */ public function sess_write() { // saving custom info db? if not, update cookie if ($this->sess_use_database === false) { $this->_set_cookie(); return; } // set custom userdata, session info set in sec $custom_userdata = $this->userdata; $cookie_userdata = array(); // before continuing, need determine if there custom info deal with. // let's determine removing default indexes see if there's left in array // , set session info while we're @ foreach (array('session_id','ip_address','user_agent','last_activity') $val) { unset($custom_userdata[$val]); $cookie_userdata[$val] = $this->userdata[$val]; } /* * begin old_session_id_changes * * old_session_id has own field, doesn't need go * cookie because we'll retrieve database. */ unset($custom_userdata['old_session_id']); /* * end old_session_id_changes */ // did find custom data? if not, turn empty array string // since there's no reason serialize , store empty array in db if (count($custom_userdata) === 0) { $custom_userdata = ''; } else { // serialize custom info array can store $custom_userdata = $this->_serialize($custom_userdata); } // run update query $this->ci->db->where('session_id', $this->userdata['session_id']); $this->ci->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata)); // write cookie. notice manually pass cookie info array // _set_cookie() function. function store $this->userdata, // in case array contains custom data, not want in cookie. $this->_set_cookie($cookie_userdata); } // -------------------------------------------------------------------- /** * update existing session * * @return void */ public function sess_update() { // update session every 5 minutes default if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now) { return; } // _set_cookie() handle if aren't using database sessions // pushing userdata cookie. $cookie_data = null; /* * begin old_session_id_changes * * don't need regenerate session if came in indexing * old_session_id), send out cookie anyway create sure * client has re-create of new cookie. * * isset check first in case we're not using database * store data. old_session_id field exists in * database. */ if ((isset($this->userdata['old_session_id'])) && ($this->cookie_session_id === $this->userdata['old_session_id'])) { // set cookie explicitly have our session info $cookie_data = array(); foreach (array('session_id','ip_address','user_agent','last_activity') $val) { $cookie_data[$val] = $this->userdata[$val]; } $this->_set_cookie($cookie_data); return; } /* * end old_session_id_changes */ // save old session id know record // update in database if need $old_sessid = $this->userdata['session_id']; $new_sessid = ''; { $new_sessid .= mt_rand(0, mt_getrandmax()); } while (strlen($new_sessid) < 32); // create session id more secure we'll combine user's ip $new_sessid .= $this->ci->input->ip_address(); // turn hash , update session info array $this->userdata['session_id'] = $new_sessid = md5(uniqid($new_sessid, true)); $this->userdata['last_activity'] = $this->now; // update session id , last_activity field in db if needed if ($this->sess_use_database === true) { // set cookie explicitly have our session info $cookie_data = array(); foreach (array('session_id','ip_address','user_agent','last_activity') $val) { $cookie_data[$val] = $this->userdata[$val]; } /* * begin old_session_id_changes * * save old session id old_session_id field * can reference later. * * rewrite cookie's session id if there 0 affected rows * because means request changed database * under current request. in case, want homecoming * value consistent previous request. reread * after update phone call here minimize timing problems. * should in transaction databases back upwards them. * * rewrite userdata future calls sess_write * output right cookie data. * * used be: * $this->ci->db->query($this->ci->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid))); */ $this->ci->db->query($this->ci->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid, 'old_session_id' => $old_sessid), array('session_id' => $old_sessid))); if ($this->ci->db->affected_rows() === 0) { $this->ci->db->where('old_session_id', $this->cookie_session_id); $query = $this->ci->db->get($this->sess_table_name); // we've lost track of session if there no results, // don't set cookie , return. if ($query->num_rows() == 0) { return; } $row = $query->row(); foreach (array('session_id','ip_address','user_agent','last_activity') $val) { $this->userdata[$val] = $row->$val; $cookie_data[$val] = $this->userdata[$val]; } // set request session id old session id // won't seek regenerate cookie 1 time again on request -- // in case sess_update ever called 1 time again (which // shouldn't be). $this->cookie_session_id = $this->userdata['old_session_id']; } /* * end old_session_id_changes */ } // write cookie $this->_set_cookie($cookie_data); } /********************************************************************* * end overrides codeigniter session library *********************************************************************/
php codeigniter session