codeigniter-session-memcached
codeigniter-session-memcached copied to clipboard
session expires randomly after 5-10 mins
I am using this for my website, normally it would work fine , but after 5-10 mins randomly it would expire the session. I have set session timeout value to 2 days but still then this happens
my current config
$config['sess_cookie_name'] = 'ci_session'; $config['sess_expiration'] = 1209600; $config['sess_expire_on_close'] = FALSE; $config['sess_encrypt_cookie'] = TRUE; $config['sess_use_database'] = FALSE; $config['sess_table_name'] = 'ci_sessions'; $config['sess_match_ip'] = FALSE; $config['sess_match_useragent'] = TRUE; $config['sess_time_to_update'] = 300;
/* |--------------------------------------------------------------------------
Memcached Session Variables |
---|
"session_storage" = where you will be storing your session data. Accepts "memcached", "database", "cookie" |
"memcache_ports" = the port that you will connect to memcache on |
"memcached_nodes" = array of IP addresses of Memcached nodes |
*/ |
$config['session_storage'] = 'memcached'; |
$config ['memcached_port'] = '11211'; |
$config['memcached_nodes'] = array('127.0.0.1'); |
can u please help me to fix this issue? I cant get anything reason for this behaviur
Yeah that's the reason it's not production ready yet. There's a link in the README file which explains it.
seems that it is due to memcache miss, maybe you should implement a failover mechanism ?
I think this is related to the sess_write() function. When you write user_data to the session the session_id is not written to memcache.
When the class fetches the key from memcache there is not session_id and thus it will fail and log you out.
case 'database':
// Run the 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));
break;
case 'memcached':
$this->memcache->replace("user_session_data" . $this->userdata['session_id'], array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata), false, $this->sess_expiration);
log_message('debug', 'session written to memcache');
break;
}
I'm testing a fix right now
@dennisvdvliet: Did u find any solution ? Let me know! I am eagerly waiting for the solution!
//rebuild array
$save = array(
'session_id' => $this->userdata['session_id'],
'ip_address' => $this->CI->input->ip_address(),
'user_agent' => substr($this->CI->input->user_agent(), 0, 50),
'last_activity' => $this->now,
'user_data' => $custom_userdata
);
switch ($this->session_storage) {
case 'database':
// Update the session ID and last_activity field in the DB if needed
// set cookie explicitly to only have our session data
$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)));
break;
case 'memcached':
// Add item with new session_id and data to memcached
// then delete old memcache item
// save the whole array instead of updating
$r = $this->memcached->set('user_session_data' . $new_sessid, $save,$this->sess_expiration+600);
$this->memcached->delete('user_session_data' . $old_sessid);
@kingster what i did to fix it is rebuild the session array and save that to memcached. See code snippet
I think that $custom_userdata is not defined in this function instance ( sess_update()
)
I think before the //rebuild array this needs to be added
I will test this and let u know, hope that this solves the problem :)
@kingster I tried that and that did not work on all occasions. The code I posted has been used for a couple of weeks since mid-september and people are not logged out anymore on our site.
But keep me posted
This is for sess_update() function or sess_write() ??
@kingster I use it both
Sorry for the late reply
Hi
Can you send me your file at kinshuk1989[at]gmail[dot]com or atleast your copy in github please? I tried but mine didnt work.
@kingster
The solution to this bug, just replace your sess_update with:
function sess_update() {
// We only update the session every five minutes by default
if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now) {
log_message('info','not enough time before update');
return;
}
log_message('info','MC defo need to update session');
// Save the old session id so we know which record to
// update in the database if we need it
$old_sessid = $this->userdata['session_id'];
$new_sessid = '';
while (strlen($new_sessid) < 32) {
$new_sessid .= mt_rand(0, mt_getrandmax());
}
// To make the session ID even more secure we'll combine it with the user's IP
$new_sessid .= $this->CI->input->ip_address();
// Turn it into a hash
$new_sessid = md5(uniqid($new_sessid, TRUE));
log_message('info','session id generated');
// Update the session data in the session data array
$this->userdata['session_id'] = $new_sessid;
$this->userdata['last_activity'] = $this->now;
// _set_cookie() will handle this for us if we aren't using database sessions
// by pushing all userdata to the cookie.
$cookie_data = NULL;
$cookie_data = array();
$mem_data = array();
$cookie_keys = array('session_id', 'ip_address', 'user_agent', 'last_activity');
foreach ($cookie_keys as $key) {
$cookie_data[$key] = $this->userdata[$key];
}
foreach ($this->userdata as $key => $value) {
if (in_array($key, $cookie_keys))
continue;
$mem_data[$key] = $this->userdata[$key];
}
$save = array(
'session_id' => $cookie_data['session_id'],
'ip_address' => $cookie_data['ip_address'],
'user_agent' => $cookie_data['user_agent'],
'last_activity' => $this->now,
'user_data' => $this->_serialize($mem_data)
);
switch ($this->session_storage) {
case 'database':
// Update the session ID and last_activity field in the DB if needed
// set cookie explicitly to only have our session data
$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)));
break;
case 'memcached':
// Add item with new session_id and data to memcached
// then delete old memcache item
$this->memcached->set('user_session_data' . $new_sessid, $save, $this->sess_expiration);
log_message('info', 'MC new session added' . $this->sess_expiration);
$this->memcached->delete('user_session_data' . $old_sessid);
log_message('info', 'MC old session deleted');
break;
}
unset($mem_data);
// Write the cookie
$this->_set_cookie($cookie_data);
}
clockwork! This saved me the pain of having to figure out what was messing my cookies and sessions