codeigniter-session-memcached icon indicating copy to clipboard operation
codeigniter-session-memcached copied to clipboard

session expires randomly after 5-10 mins

Open kingster opened this issue 13 years ago • 12 comments

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

kingster avatar Jun 16 '11 12:06 kingster

Yeah that's the reason it's not production ready yet. There's a link in the README file which explains it.

pierskarsenbarg avatar Jun 16 '11 13:06 pierskarsenbarg

seems that it is due to memcache miss, maybe you should implement a failover mechanism ?

kingster avatar Jun 17 '11 05:06 kingster

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 avatar Sep 15 '11 15:09 dennisvdvliet

@dennisvdvliet: Did u find any solution ? Let me know! I am eagerly waiting for the solution!

kingster avatar Sep 22 '11 12:09 kingster


//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

dennisvdvliet avatar Oct 21 '11 10:10 dennisvdvliet

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 avatar Oct 21 '11 11:10 kingster

@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

dennisvdvliet avatar Oct 21 '11 12:10 dennisvdvliet

This is for sess_update() function or sess_write() ??

kingster avatar Oct 21 '11 12:10 kingster

@kingster I use it both

Sorry for the late reply

dennisvdvliet avatar Feb 21 '12 16:02 dennisvdvliet

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 avatar Feb 21 '12 17:02 kingster

@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);
    }

agustinprod avatar Jul 12 '12 18:07 agustinprod

clockwork! This saved me the pain of having to figure out what was messing my cookies and sessions

kevosomi avatar Sep 06 '14 01:09 kevosomi