phpoopsessionsession-set-save-handler

session_set_save_handler() w/ session timeout


I currently have a class containing the session_set_saver_handlerit's working fine. However I am wanting to implement a session timeout which is causing more problems than first anticipated.

As far as I am aware the session lifecycle is as follows;

calling session_destroy() would then run _destroy() which would run my configuration that I've set.

The class writes direct to a database to store my sessions. The database contains the following columns;

So, currently I have the below;

public function _read($id) 
    {

        $timeout = time() - 30;

        $this->database->query('SELECT updatedTime, data FROM sessions WHERE session = :id');
        $this->database->bind(':id', $id); 

        if($this->database->execute())
        {
            if($this->database->rowCount() > 0)
            {
                $row = $this->database->singleResult();

                if($row['updatedTime'] < $timeout)
                {
                    session_unset();
                    session_destroy(); 
                    return; 
                }

                return $row['data']; 
            }
        }

        return '';
    }

public function _destroy($id) 
    {
        $locked = true; 

        $this->database->query('UPDATE sessions SET locked = :locked WHERE session = :id');
        $this->database->bind(':locked', $locked); 
        $this->database->bind(':id', $id); 

        if($this->database->execute())
        {
            return true; 
        } 

        return false;
    }

When the condition is true ( $row['updatedTime'] < $timeout ) it runs session_destroy however because it relies on a database object passed to the class this is destroyed when session_destroy is ran meaning there is no active db connection. Well, this is as far as I understand what is happening. I might of understood this completely wrong.

The 30 second timeout is for testing purposes only. Okay, so what I'm after is when the last activity of the session exceeds the current set timeout it needs to destroy the session and set the locked column to true.

Thanks!


Solution

  • You don't need to call session_destroy() there. If the session is expired, just call header('Location: logout.php') or whatever else you want to happen. In your logout.php file call session_destroy(); and redirect to login page.

    To clean after the expired session you will need to define your garbage collection function (sixth parameter in session_set_save_handler), where you will do all that staff you do for current session in destroy function, but selecting only expired sessions.

    Besides, I would just delete the record of that session instead of setting it to "locked" - you will never go back to that session, will you?

    Also, in _destroy function you can delete the session cookie:

    if(isset($_COOKIE['PHPSESSID'])){
        setcookie("PHPSESSID",$_COOKIE['PHPSESSID'],time() - 100000,"/");
    }
    

    To prevent session fixation attack (where user reuse the same session id, or steal that id and puts it into his session cookie), call session_regenerate_id(true); just after logging the user in.