1

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;

  • open
  • read
  • write
  • close

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;

  • session; contains the sessionID
  • data; contains the data of the session
  • updatedTime; contains the last activity of the session
  • locked; Default is false. However if $variable < $access this is set to true

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!

jakehallas
  • 2,456
  • 1
  • 18
  • 26

1 Answers1

1

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.

n-dru
  • 9,285
  • 2
  • 29
  • 42
  • That last bit is a highly dangerous like this - you should [retrieve the actual cookie name](http://php.net/manual/en/function.session-name.php) instead of relying on a configurable default. – Niels Keurentjes Jun 30 '15 at 13:13
  • Calling the `header(...)` works great! However wouldn't the user keep the same session because it's not actually "destroyed"? From my understanding, the gc is dependant on the php.ini configuration and is ran under the conditions configure in php.ini? I would like to handle the session closure at the point of redirecting the user with header().. if that makes sense? – jakehallas Jun 30 '15 at 14:10
  • I updated the answer - you can call `session_destroy();` in `logout.php` and redirect to login page, that way this session will be destroyed in the same way like when the user clicks on `logout` button. – n-dru Jun 30 '15 at 14:35
  • Brilliant! That was very simple, I cannot believe a missed that! Thanks a lot, much appreciated. – jakehallas Jun 30 '15 at 14:52