Destroying a specific session in Code Igniter

I want to be able to log users out of my app built in Code Igniter.

I know how to end an active local session:

$this->session->sess_destroy();

But how can I destroy a session that was started on another computer and thereby log a user out of their session?

I store a unique id associated with their account in the session data, so I can see it in the session table in the database, but it is stored along with the other session data in a column called user_data, the contents of which look something like this:

a:4:
{s:9:"user_data";s:0:"";s:6:"userid";s:6:"189034";s:9:"logged_in";b:1;s:5:"token";i:1767727789;}

where 189034 is the user's id.

So, is there a way to somehow select the row in the session table based on the user's id, and then delete the row and destroy the session. Or is there another way to do this entirely?


Solution 1:

Create a new column in the ci_session table.

ALTER TABLE `yourdatabase`.`ci_sessions` 
ADD COLUMN `userid` VARCHAR(45) NULL  AFTER `user_data` ;

Then in your login function get the id from your login process and before adding the userdata information to the session do:

/* Delete any existing sessions with the current userid session.
Note - a new session has already been generated but doesn't have a value
in the userid column, so won't get deleted. */
$this->db->delete('ci_sessions',array('userid' => $identity));    

// Get the current session and update it with the userid value.
$session_id = $this->session->userdata('session_id');
$this->db->where('session_id', $session_id);
$this->db->update('ci_sessions', array('userid' => $identity));

Where $identity is your userid. That clears any previous sessions and means only one exists at a time.

Solution 2:

There is the function to destroy some items/session you want

$this->session->unset_userdata('session_name')

And to allow one user to log in one computer at a time or one browser at a time you can read more here

Allow one session only at a time

Solution 3:

One of the problems with serialized data is that there's no legitimate way to query it. You'll have to get all users in the session (could be a lot) and unpack the data, check for the value, then delete the row in the session table, effectively destroying that session.

foreach ($this->db->get('sessions')->result() as $session)
{
    $data = unserialize($session->user_data);

    if ( ! isset($data['user_id'])) continue;

    if ($data['user_id'] === $id_to_delete)
    {
        // delete the row
            $this->db->where('session_id', $session->session_id)
                ->delete('sessions');
    }
}

I would probably discourage this. Every user on your site, logged in or not, has a session that would have to be picked through, and remember: one user could possibly have more than one session so you'd have to cycle through every one.

Another approach could be to add a custom column to the session table with the user id (or a hash of the id). Something that you can query against to find the user's session quickly. Then, when you add the user_id to the session, populate this column, and when you need to delete the session by user_id it can be done quickly and efficiently.