Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flashdata bug #1756

Closed
mspiderv opened this issue Sep 1, 2012 · 9 comments
Closed

Flashdata bug #1756

mspiderv opened this issue Sep 1, 2012 · 9 comments

Comments

@mspiderv
Copy link

mspiderv commented Sep 1, 2012

Set
$db['default']['cache_on'] = TRUE;
and...
$config['sess_use_database'] = TRUE;

Flashdata will not work correctly.

@GDmac
Copy link
Contributor

GDmac commented Sep 3, 2012

Which version of CI are you using?
Are you using the latest develop version with the session driver-based library?

@mspiderv
Copy link
Author

mspiderv commented Sep 3, 2012

Im using CI 2.1.2, but Im not sure, that I use driver-based session library. I think I use normal session library. The location of my session library file is ./system/libraries/Session.php. Please set $db['default']['cache_on'] = TRUE; and config['sess_use_database'] = TRUE; in your config and try it yourself.

@GDmac
Copy link
Contributor

GDmac commented Sep 4, 2012

Yes, using database cache in combination with using session database is an issue
"in CodeIgniter caching is an all-or-nothing solution." via: stackoverflow
The Stackoverflow answer suggests using a caching library like http://philsturgeon.co.uk/code/codeigniter-cache

Solution:
in 2.1.2 system/libraries/session.php, line 213, in the method sess_read(),
before running the query, disable db_caching temporarily.

  // store current db_cache state and disable cache
  $db_cache_state = $this->CI->db->cache_on;
  $this->CI->db->cache_off();

  $query = $this->CI->db->get($this->sess_table_name);

  // restore db cache state if needed 
  if ($db_cache_state === TRUE) $this->CI->db->cache_on();

Maybe @philsturgeon or @alexbilbie or @pkriete from the dev team
can have a look if this can be included in the 2.x tree

@GDmac
Copy link
Contributor

GDmac commented Sep 4, 2012

@dchill42 this should probably also go into the session driver from the 3.x develop tree

@mspiderv
Copy link
Author

mspiderv commented Sep 4, 2012

Your solution did not work for me :/ But I fixed it with following code.

// this is the begining of write method in /system/database/DB_cache.php
function write($sql, $object)
{
            $sql = str_replace("\n", ' ', $sql);

            if(config_item('sess_use_database'))
            {
                $banned_prefex = 'SELECT * FROM (`' . config_item('sess_table_name') . '`)';
                if(substr($sql, 0, strlen($banned_prefex)) == $banned_prefex) return TRUE;
            }
            ...
            ...
            ...

Sorry for my english.

@dchill42
Copy link
Contributor

dchill42 commented Sep 4, 2012

@GDmac that looks like a good fix. If caching is disabled during a query, the cache is bypassed and the query is actually run. I'm curious as to why it didn't seem to work for @mspiderv.

That is the only place in the code where session data is read from the DB, and disabling caching around that query should prevent both reading from and writing to the cache for that lookup. In fact, that's a more efficient solution than selectively disabling cache writes for the session table, where the DB cache driver is still going to search for a (missing) match on every session load.

Nonetheless, if the temporary cache disable was tried in the real world and failed, I'd like to know why.

@mspiderv mspiderv closed this as completed Sep 4, 2012
@mspiderv mspiderv reopened this Sep 4, 2012
@mspiderv
Copy link
Author

mspiderv commented Sep 4, 2012

Ohh @GDmac was right. Sorry. Your fix works. It did not work for me, because I had some files cached and probably CI received data from them. After I deleted all cached files, session wokrs correctly. Thank you all.

If you have the same problem, use this code.

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class MY_Session extends CI_Session {

    /**
     * Fetch the current session data if it exists
     *
     * @access  public
     * @return  bool
     */
    function sess_read()
    {
        // Fetch the cookie
        $session = $this->CI->input->cookie($this->sess_cookie_name);

        // No cookie?  Goodbye cruel world!...
        if ($session === FALSE)
        {
            log_message('debug', 'A session cookie was not found.');
            return FALSE;
        }

        // Decrypt the cookie data
        if ($this->sess_encrypt_cookie == TRUE)
        {
            $session = $this->CI->encrypt->decode($session);
        }
        else
        {
            // encryption was not used, so we need to check the md5 hash
            $hash    = substr($session, strlen($session)-32); // get last 32 chars
            $session = substr($session, 0, strlen($session)-32);

            // Does the md5 hash match?  This is to prevent manipulation of session data in userspace
            if ($hash !==  md5($session.$this->encryption_key))
            {
                log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
                $this->sess_destroy();
                return FALSE;
            }
        }

        // Unserialize the session array
        $session = $this->_unserialize($session);

        // Is the session data we unserialized an array with the correct format?
        if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity']))
        {
            $this->sess_destroy();
            return FALSE;
        }

        // Is the session current?
        if (($session['last_activity'] + $this->sess_expiration) < $this->now)
        {
            $this->sess_destroy();
            return FALSE;
        }

        // Does the IP Match?
        if ($this->sess_match_ip == TRUE AND $session['ip_address'] != $this->CI->input->ip_address())
        {
            $this->sess_destroy();
            return FALSE;
        }

        // Does the User Agent Match?
        if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 120)))
        {
            $this->sess_destroy();
            return FALSE;
        }

        // Is there a corresponding session in the DB?
        if ($this->sess_use_database === TRUE)
        {
            $this->CI->db->where('session_id', $session['session_id']);

            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']);
            }

            $cache_on = $this->CI->db->cache_on;
            $this->CI->db->cache_on = FALSE;

            $query = $this->CI->db->get($this->sess_table_name);

            $this->CI->db->cache_on = $cache_on;

            // No result?  Kill it!
            if ($query->num_rows() == 0)
            {
                $this->sess_destroy();
                return FALSE;
            }

            // Is there custom data?  If so, add it to the main session array
            $row = $query->row();
            if (isset($row->user_data) AND $row->user_data != '')
            {
                $custom_data = $this->_unserialize($row->user_data);

                if (is_array($custom_data))
                {
                    foreach ($custom_data as $key => $val)
                    {
                        $session[$key] = $val;
                    }
                }
            }
        }

        // Session is valid!
        $this->userdata = $session;
        unset($session);

        return TRUE;
    }

}

@mspiderv mspiderv closed this as completed Sep 4, 2012
@dchill42
Copy link
Contributor

dchill42 commented Sep 4, 2012

I will put up a pull request with this fix for the Session driver.

dchill42 added a commit to dchill42/CodeIgniter that referenced this issue Sep 4, 2012
Signed-off-by: dchill42 <dchill42@gmail.com>
@dchill42
Copy link
Contributor

dchill42 commented Sep 4, 2012

Applied this change in #1770.

alexbilbie added a commit that referenced this issue Sep 5, 2012
nonchip pushed a commit to nonchip/CodeIgniter that referenced this issue Jun 29, 2013
Signed-off-by: dchill42 <dchill42@gmail.com>
nonchip pushed a commit to nonchip/CodeIgniter that referenced this issue Jun 29, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants