ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

CI, Sessions, Ajax and expiration

December 23, 2010 10:37am

Subscribe [2]
  • #1 / Dec 23, 2010 10:37am

    Codepeak

    7 posts

    OK this error has been bugging me for several days now and it’s very annoying since I really can’t find the real problem and solve it.

    Anyway, I’ll try to explain everything.

    Storing my sessions in the database.

    1. A user logs in using his username+password. A session is created with the users_id stored in the CI session table. The session library is automatically loaded on every page load (set in config/autoload.php).

    2. There is a user class that’s also auto loaded. That class updates the session to store the current page the user is visiting and a random value.

    $this->CI->session->set_userdata('current_page', uri_string());
    $this->CI->session->set_userdata('rnd_number', time());

    That also works like a charm.

    3. When the user goes to the chat the weird stuff starts to happen. And that’s where the main problem is I guess.

    The chat page is only loaded once, the rest is handled by AJAX requests (using jQuery).

    The following requests is done:

    - Every 2 sec a request is made to a ajax controller to see if there is any new messages to display.

    - Every 3 sec a request is made to a ajax controller to update some other HTML on the page

    - Every 10 sec a request is made to update a small notification bar on the page.

    If a user has been on the page for too long ( longer than $config[‘sess_expiration’] ) the user will be logged out. Even though each ajax requests would cause the User library to update the users session.

    OK, since cookies on the users computer is used also from that I’ve understand of the documentation, we need to update the users cookies since that won’t be done in the ajax requests.

    I’ve added a 1x1 transparent iframe at the bottom of each page that will reload every minute. The page that’s loaded is a very stripped down page to minimize bandwidth used. Though that would keep the session alive. But still, after $config[‘sess_expiration’] has passed the user is logged out.

    Checking the database the user_data field is updated as expected. “last_activity” field is updated every $config[‘sess_time_to_update’] second and a new `sessionid` is set.

    As a temporary fix that’s not a nice fix I’ve changed the configuration to this:

    $config['sess_cookie_name']        = 'session';
    $config['sess_expiration']        = (6*3600);
    $config['sess_encrypt_cookie']    = TRUE;
    $config['sess_use_database']    = TRUE;
    $config['sess_table_name']        = 'sessions';
    $config['sess_match_ip']        = FALSE;
    $config['sess_match_useragent']    = FALSE;
    $config['sess_time_to_update']     = 300;

    The lifetime of the session is set to 6 hour (praying that no one stays on the chat for 6 straight hours). The users using the page won’t be logged out, but users who left the page will remain online for 6 more hours. The problem still exists that some people (including me) gets logged out for no reason even before the 6h has passed.

    The setup I think should work best would be this:

    $config['sess_cookie_name']        = 'session';
    $config['sess_expiration']        = 900;
    $config['sess_encrypt_cookie']    = TRUE;
    $config['sess_use_database']    = TRUE;
    $config['sess_table_name']        = 'sessions';
    $config['sess_match_ip']        = FALSE;
    $config['sess_match_useragent']    = FALSE;
    $config['sess_time_to_update']     = 60;

    The user will be automatically removed from the session table if no actions has been done in 15 minutes (900s) and the session will be updated every minute (60s). But that just makes them logout/timeout even faster.

    To be noted, I’ve added a exit(); call after each ajax request to prevent further output (shouldn’t be any though) that might mess up the json string for the javascript.

    Am I doing something very wrong or is this the way sessions should work? Should I do something different or create my own session handler?

    Thanks in advance for any replies and hope you all have a Merry Christmas!

  • #2 / Dec 23, 2010 10:40am

    Codepeak

    7 posts

    Just hit me, maybe I should some how disable the session update in ajax requests? If the session id is regenerated during a ajax request, the iframe will have the wrong data and the user will be logged out…

  • #3 / Dec 23, 2010 11:19am

    Federico Baña

    41 posts

    It comes to my mind that the iframe could be regenerating the cookie that’s related to the CI session, but the ajax is still sending the old one.
    You should try using firebug to check the status of the cookie on both the frame and the main window.

    I’ve never had to face this issue before, but im quite sure i’ll do in the future… so if you find a solution please post it back 😊

  • #4 / Dec 23, 2010 11:52am

    Codepeak

    7 posts

    Good idea! I’ll check the cookie being sent by the AJAX request.

    Here’s a modification to the Session library to not to do any write or update actions if the controller is ajax. Not fully optimized or nicely done, but does what it should during my debugging. I’ve also added log_message to almost every line of the session library so I can see what and where it goes wrong 😊

    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    
    class My_Session extends CI_Session {
    
        /**
         * Check if it's a ajax request
         * 
         * If the current call is a ajax request, determinated
         * by POST-variable is_ajax, then the session should
         * not be updated.
         * 
         * Every AJAX request should POST the variable is_ajax
         * to the controller to have this work.
         * 
         */
        
        var $myCI = FALSE;
    
        function load_my_CI()
        {
            if ( $this->myCI === FALSE )
            {
                $this->myCI =& get_instance();
            }
            return;
        }
        
        function sess_update()
        {
            $this->load_my_CI();
            if ( $this->myCI->uri->segment(1) !== 'ajax' )
            {
                parent::sess_update();
            }
        }
        
        function sess_write()
        {
            $this->load_my_CI();
            if ( $this->myCI->uri->segment(1) !== 'ajax' )
            {
                parent::sess_write();
            }
        }
    }
  • #5 / Dec 23, 2010 12:09pm

    Codepeak

    7 posts

    It comes to my mind that the iframe could be regenerating the cookie that’s related to the CI session, but the ajax is still sending the old one.
    You should try using firebug to check the status of the cookie on both the frame and the main window.

    I’ve never had to face this issue before, but im quite sure i’ll do in the future… so if you find a solution please post it back 😊

    OK, you were right. The session doesn’t change in jQuery, it’s still the old one since the IFRAME refreshes and gets new cookie values. Missmatch, logout.

    Now it’s time to figure our how to reload cookies before every ajax-request I guess… Back to Google. I’ll keep this thread updated!

  • #6 / Dec 23, 2010 1:26pm

    Federico Baña

    41 posts

    I guess the only way to get the new cookies is refrshing the page..
    Also session cookies are not visible on the client

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases