Welcome Guest, Not a member yet? Register   Sign In
losing session data
#1

[eluser]St0neyx[/eluser]
Hi,

I have this problem with the session and i can’t figure it out.

I have this controller that handles multiple form steps:
Stripped a lot of code (validation, setters, getters, etc), but this is basically what happens

Code:
function add_article($page, $mode=new, $id = null)
{
// some validating

switch ($page)
{
    case 'step_one':
        $this->session->set_userdata('step_one_progress', 'started');
        
        if (this->input->post('step_one'))
        {
            // set some form validation

            if ($this->form_validation->run() == false)
            {
                $this->load->view('templates/step_one.php', $data);
            }
            else
            {
                $this->session->set_userdata('step_one_progress', 'finished');
                redirect($data->next_page);
            }
        }
        else
        {
            // no post so show form
            $this->load->view('templates/step_one.php', $data);
        }
        break;

    case 'step_two':
        if ($this->session->userdata('step_one') == 'finished')
        {
            $this->session->set_userdata('step_two_progress', 'started');    
        
            if (this->input->post('step_two'))
            {
                if ($this->form_validation->run() == false)
                {
                    $this->load->view('templates/step_two.php', $data);
                }
                else
                {
                    $this->session->set_userdata('step_two_progress', 'finished');
                    redirect($data->next_page);
                }
            }
            else
            {
                $this->load->view('templates/step_two.php', $data);
            }
        }
        else
        {
            // previous step not yett finished, redirect back
            redirect($data->previousPage);
        }
        break;


    case 'step_three':
        if ($this->session->userdata('step_two') == 'finished')
        {
            $this->session->set_userdata('step_three_progress', 'started');    
        
            if (this->input->post('step_three'))
            {
                if ($this->form_validation->run() == false)
                {
                    $this->load->view('templates/step_three.php', $data);
                }
                else
                {
                    $this->session->set_userdata('step_three_progress', 'finished');
                    redirect($data->next_page);
                }
            }
            else
            {
                $this->load->view('templates/step_three.php', $data);
            }
        }
        else
        {
            // previous step not yett finished, redirect back
            redirect($data->previousPage);
        }
        break;
    
    default:
        redirect('/home');
        break;
} // end switch

} // end controller

From step one to step two there is no session data lost.
But when i try to proceed to step three the progress var is lost, so it can't proceed because of the check on progress.

I turned debugging on to see what is happening, also added some extra logging.

Here is the result:
INFO - 2010-11-25 14:02:20 --> case step_two = finished
INFO - 2010-11-25 14:02:20 --> Session: Array
(

[session_id] => 9b68f61e252a062681760a9cd7716fd8
[ip_address] => 10.2.0.113
[user_agent] => Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Ap
[step_one_progress] => finished
[step_two_progress] => finished
)

INFO - 2010-11-25 14:02:20 --> redirect: add_article/step_three/new/

DEBUG - 2010-11-25 14:02:20 --> Config Class Initialized
DEBUG - 2010-11-25 14:02:20 --> Hooks Class Initialized
DEBUG - 2010-11-25 14:02:20 --> URI Class Initialized
DEBUG - 2010-11-25 14:02:20 --> Router Class Initialized
DEBUG - 2010-11-25 14:02:20 --> Output Class Initialized
DEBUG - 2010-11-25 14:02:20 --> Input Class Initialized
DEBUG - 2010-11-25 14:02:20 --> XSS Filtering completed
DEBUG - 2010-11-25 14:02:20 --> XSS Filtering completed
DEBUG - 2010-11-25 14:02:20 --> XSS Filtering completed
DEBUG - 2010-11-25 14:02:20 --> Global POST and COOKIE data sanitized
DEBUG - 2010-11-25 14:02:20 --> Language Class Initialized
DEBUG - 2010-11-25 14:02:20 --> Loader Class Initialized
DEBUG - 2010-11-25 14:02:20 --> Config file loaded: config/qoop.php
DEBUG - 2010-11-25 14:02:20 --> Helper loaded: url_helper
DEBUG - 2010-11-25 14:02:20 --> Helper loaded: project_helper
DEBUG - 2010-11-25 14:02:20 --> Helper loaded: xsl_helper
DEBUG - 2010-11-25 14:02:20 --> Helper loaded: menu_helper
DEBUG - 2010-11-25 14:02:20 --> Helper loaded: message_helper
DEBUG - 2010-11-25 14:02:20 --> Helper loaded: breadcrumb_helper
DEBUG - 2010-11-25 14:02:20 --> Database Driver Class Initialized
DEBUG - 2010-11-25 14:02:20 --> Session Class Initialized
DEBUG - 2010-11-25 14:02:20 --> before session init, session is: Array
(
)
DEBUG - 2010-11-25 14:02:20 --> Helper loaded: string_helper
DEBUG - 2010-11-25 14:02:20 --> Encrypt Class Initialized
DEBUG - 2010-11-25 14:02:20 --> Session routines successfully run
DEBUG - 2010-11-25 14:02:20 --> after session init: Array
(

[session_id] => 9b68f61e252a062681760a9cd7716fd8
[ip_address] => 10.2.0.113
[user_agent] => Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Ap
[step_one_progress] => finished
[step_two_progress] => started
)

For some reason the progress is reseted to started, but the code doesn't come there (else there would be an extra loggin line).

Is this an bug in the session (to much redirecting)?

any suggestions?
#2

[eluser]WanWizard[/eluser]
Database sessions? Cookie sessions? Third-party library? Which webserver, which browser?

Cookies and redirects are always tricky business, there are browsers that ignore any http header when the header contains a "location" redirect...
#3

[eluser]St0neyx[/eluser]
[quote author="WanWizard" date="1290717770"]Database sessions? Cookie sessions? Third-party library? Which webserver, which browser?
[/quote]

At this point i'm still using the codeigniter session class with cookie sessions.
No third party library's at this part of the application.
The browser is every browser, i mostly develop in FF/Chrome but it also happend in IE/Opera/Safari.

Webserver is apache : running under debian (Debian 2.6.26-25lenny1).
#4

[eluser]St0neyx[/eluser]
Fixed the problem by using the Third-party library db_session.
Instead of writing data to the session it's now written to the db (without the usage of cookies).

This is maybe slower but on the other hand now i can use more then 4kb of data (cookie limit).

And it all is server-side now (accept for the session_id)

Still it's strange that the data was overwritten, didn't find out why...
#5

[eluser]WanWizard[/eluser]
It would have helped to read the user guide. CI sessions do use the database, you just need to configure it. No need for third party libraries.
#6

[eluser]St0neyx[/eluser]
[quote author="WanWizard" date="1290737041"]It would have helped to read the user guide. CI sessions do use the database, you just need to configure it. No need for third party libraries.[/quote]

I did read the user guide and i did tried it the CI way, enabling the database option puts the data in the db true, but when you retrieve data from the "session" it still is stored in cookies therefor the limit still is 4kb.

The Third-party lib i used extend to the session class, when data is retrieved instead of putting it in the cookie it put's it in an array and therefor the limit is gone.

But this is a workaround for the session limit. Still leaves the question open why session data is reseted after redirect.
#7

[eluser]InsiteFX[/eluser]
WanWizard is right!

You must not have read the Session Class!

Because if you did you would know that the session class doe's not
store the user_data in the cookie!

InsiteFX
#8

[eluser]St0neyx[/eluser]
[quote author="InsiteFX" date="1290784081"]WanWizard is right!

You must not have read the Session Class!

Because if you did you would know that the session class doe's not
store the user_data in the cookie!

InsiteFX[/quote]

The user guide says that yes, but when i started testing it i came to different outcome.
So i opened Session.php (the library CI provides) to analyze the code.

Now just for fun look at this:
Code:
function set_userdata($newdata = array(), $newval = '')
{
    if (is_string($newdata))
    {
        $newdata = array($newdata => $newval);
    }

    if (count($newdata) > 0)
    {
        foreach ($newdata as $key => $val)
        {
            $this->userdata[$key] = $val;
        }
    }

    // write the session
    $this->sess_write();
}

function sess_write()
{
    // Are we saving custom data to the DB?  If not, all we do is update the cookie
    if ($this->sess_use_database === FALSE)
    {
        $this->_set_cookie();
        return;
    }

    // set the custom userdata, the session data we will set in a second
    $custom_userdata = $this->userdata;
    $cookie_userdata = array();

    // Before continuing, we need to determine if there is any custom data to deal with.
    // Let's determine this by removing the default indexes to see if there's anything left in the array
    // and set the session data while we're at it
    foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
    {
        unset($custom_userdata[$val]);
        $cookie_userdata[$val] = $this->userdata[$val];
    }

    // Did we find any custom data?  If not, we turn the empty array into a string
    // since there's no reason to serialize and store an empty array in the DB
    if (count($custom_userdata) === 0)
    {
        $custom_userdata = '';
    }
    else
    {
        // Serialize the custom data array so we can store it
        $custom_userdata = $this->_serialize($custom_userdata);
    }

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

    // Write the cookie.  Notice that we manually pass the cookie data array to the
    // _set_cookie() function. Normally that function will store $this->userdata, but
    // in this case that array contains custom data, which we do not want in the cookie.
    $this->_set_cookie($cookie_userdata);
}

Now could you explain the last line of sess_write() to me? seems like it's writing an cookie...

So therefor i say, it still writes cookies..
#9

[eluser]Narkboy[/eluser]
[quote author="St0neyx" date="1290784916"]
Now could you explain the last line of sess_write() to me? seems like it's writing an cookie...

So therefor i say, it still writes cookies..[/quote]

Yes. The cookie stores the session ID. Without a copy of the session ID, the client cannot confim it's identity to the server.

Basically - the server reads the session cookie from the client, queries the database for a matching session record, and loads the content. From there, the developer can access that through $this->session->foo.

Since CI updates the session ID on a frequent basis, the cookie needs to be rewritten to contain the current ID. If we didn't re-write the cookie, then the browser would have an older version of the session ID and not be able to identify itself.

Crucually, session 'userdata' IS stored in the db and does not have a 4k limit. You can test definitevly by writing 5k+ of random text to see if it holds.

At least - that's hwat I get from the code you posted. Can't say I've ever tried to drop more than 4k into session data before though.

/B

Edit:

Also, checkout the last comment lines in the code:
Code:
// Write the cookie.  Notice that we manually pass the cookie data array to the
    // _set_cookie() function. Normally that function will store $this->userdata, but
    // in this case that array contains custom data, which we do not want in the cookie.

Smile
#10

[eluser]WanWizard[/eluser]
Correct.

This is what goes into the cookie:
Code:
foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
{
    unset($custom_userdata[$val]);
    $cookie_userdata[$val] = $this->userdata[$val];
}
and nothing more. And you will need this information to correctly match the user's session to the data stored in the backend. Every session solution uses a cookie like this.

If you store more than 4Kb in a cookie, the data in HTTP header get's truncated by the browser. As session data is encrypted, it can therefore not be decrypted anymore when you read it back (you miss data), which renders the session invalid.




Theme © iAndrew 2016 - Forum software by © MyBB