Roman
Roman

Reputation: 3749

Restore session_id in CodeIgniter

I want to destroy restore the session id and then start the session, which is done in standard PHP like following. How can I do this in CodeIgniter?

session_destroy();
session_id($old_session_id);
session_start();

I think session is started automatically by autoloading the library:

$autoload['libraries'] = array('session');

Is it so? How can I use the session_id($old_session_id); in CodeIgniter? I'm trying with $this->session->set_userdata('session_id', $old_session_id);

But it seems that something is not working fine, as i can not get the session data. Any idea if anything is wrong with the above lines or something else? Thanks.

Upvotes: 0

Views: 2046

Answers (3)

Jordi
Jordi

Reputation: 1148

If someone is working with a legacy Codeigniter project (like us) and is dealing with this problem, here you have a possible solution (for the case in which the session data is stored in the database).

  • Once you have the sessionId you want to restore, you can retrieve the session data from the database session table. The id of this table corresponds to your sessionId.
  • You must unserialize this data.
  • Then you can easily restore your session passing the unserialized data array to the "set_userdata($data)" method of the Codeigniter session class.

Here you have a working code example (please note that you must replace the $sessionDataFinder with your custom method that retrieve the session data from the database, this method return a string that contains the serialized session data, also note that the unserialize methods commes from this Stackoverflow question):

class Restoredatabasesessionlibrary

{

/** @var CI_Session $session */
private $session;

/** @var CI_Session $session */
private $session;

/** @var Sessiondatafinderlibrary $sessionDataFinder */
private $sessionDataFinder;


public function __construct()
{
    $ci = &get_instance();

    $ci->load->library(
        [
            'sessiondatafinderlibrary'
        ]
    );

    $this->sessionDataFinder = $ci->sessiondatafinderlibrary;
    $this->session = $ci->session;
}

/**
 * @throws NotFoundFinderException
 * @throws Exception
 */
public function restoreBySessionId(string $sessionId): void
{
    $serializedData = $this->sessionDataFinder->getBySessionId($sessionId);

    $data = $this->unserialize($serializedData);

    $this->session->set_userdata($data);
}

/*
 * Code from: https://stackoverflow.com/questions/530761/how-can-i-unserialize-session-data-to-an-arbitrary-variable-in-php
 * */
/**
 * @throws Exception
 */
private function unserialize($session_data): array
{
    $method = ini_get("session.serialize_handler");
    switch ($method) {
        case "php":
            return $this->unserialize_php($session_data);
        case "php_binary":
            return $this->unserialize_phpbinary($session_data);
        default:
            throw new Exception("Unsupported session.serialize_handler: " . $method . ". Supported: php, php_binary");
    }
}

private function unserialize_php($session_data): array
{
    $return_data = array();
    $offset = 0;
    while ($offset < strlen($session_data)) {
        if (strpos(substr($session_data, $offset), "|") === false) {
            throw new Exception("invalid data, remaining: " . substr($session_data, $offset));
        }
        $pos = strpos($session_data, "|", $offset);
        $num = $pos - $offset;
        $varname = substr($session_data, $offset, $num);
        $offset += $num + 1;
        $data = unserialize(substr($session_data, $offset));
        $return_data[$varname] = $data;
        $offset += strlen(serialize($data));
    }

    return $return_data;
}

private function unserialize_phpbinary($session_data): array
{
    $return_data = array();
    $offset = 0;
    while ($offset < strlen($session_data)) {
        $num = ord($session_data[$offset]);
        ++$offset;
        $varname = substr($session_data, $offset, $num);
        $offset += $num;
        $data = unserialize(substr($session_data, $offset));
        $return_data[$varname] = $data;
        $offset += strlen(serialize($data));
    }

    return $return_data;
}

}

Upvotes: 0

jason_hamiltonm
jason_hamiltonm

Reputation: 38

Some things to check for:

  1. Check to ensure sessions are working in PHP without CodeIgniter. If sessions do not work then your server is not saving session info correctly

  2. Check if you are saving session information to the database or not (In application/config/config.php does $config['sess_use_database'] equal FALSE? If TRUE, then make sure to have this code imported into your DB

 

CREATE TABLE IF NOT EXISTS  `ci_sessions` (
    session_id varchar(40) DEFAULT '0' NOT NULL,
    ip_address varchar(16) DEFAULT '0' NOT NULL,
    user_agent varchar(50) NOT NULL,
    last_activity int(10) unsigned DEFAULT 0 NOT NULL,
    user_data text DEFAULT '' NOT NULL,
    PRIMARY KEY (session_id)
);

If something is not correct here then CI is not saving session info.

  1. Try a bit more session testing using this snippet in a working controller function:

 

$this->load->library('session'); // load session in controller
echo $session_id = $this->session->userdata('session_id'); // print session id to page

Check your error logs to see if CI is loading the session library module and no errors are present.

This is more of a debugging strategy for sessions than a solution.

Upvotes: 1

Damien Pirsy
Damien Pirsy

Reputation: 25435

Sessions in CodeIgniter are different from nativ PHP session. Actually, they're not even session at all, as they are, in fact, encripted cookies (you can also use a database to store session values, but still they're not the same as php session).

Quoting from the manual: What is Session Data?

A session, as far as CodeIgniter is concerned, is simply an array containing the following information:

    The user's unique Session ID (this is a statistically random string with very strong entropy, hashed with MD5 for portability, and regenerated (by default) every five minutes)
    The user's IP Address
    The user's User Agent data (the first 50 characters of the browser data string)
    The "last activity" time stamp.

The above data is stored in a cookie as a serialized array with this prototype: [array] (
     'session_id'    => random hash,
     'ip_address'    => 'string - user IP address',
     'user_agent'    => 'string - user agent data',
     'last_activity' => timestamp )

Whenever you load a page, CI checks in cookies to see if there's a session there. If there isn't (either beacuse you didn't set it, or beacuse it's expired), the session will be created. If it's there, instead, will be automatically rigenerated by CI

If you want to use CI's native sessions, this is the way. Otherwise, you can go for native php ones (the framework is higlhy flexible), but you cannot mix the two, as they act on different levels (on the server for php, on the client for CI's session)

Upvotes: 1

Related Questions