tags:

views:

79

answers:

3

I've (so far) been handling user sessions with client-side cookies and database entries.

When the user logs in, I generate a guid and place it in a cookie on the client's computer. Then I create an entry in a 'sessions' MySQL table, and add there the guid, ip address, the username, privileges, etc. Then when the user accesses the page, I check if there's a session cookie. if so, I check the database for the guid in the cookie and make sure the ip address matches. If it does then the user is logged in with the rest of the information in the db table. If something is wrong (bad ip address, expired session, etc) I remove the database entry and remove the guid cookie.

I've never used the $_SESSION global before.

Is my way good practice or do I need to re-think how I'm handling this?

+1  A: 

The way you're doing it now is good if you somehow need to link the current user to other database information.

Using sessions is the preferred way to do it for simplicity. I suggest you read a bit about it on www.php.net/sessions and make up your mind from that. It's very easy to use, but it is less flexible than using a database table. You can still set all the values you need, but you'd then have to fetch them and insert them into the query whenever you need to use them for database operations.

Tor Valamo
that's a good point, but I think zombats session handler class makes the database portion of sessions a little more seamless.
Carson Myers
+1  A: 

I think you are on the right track. It really is going to depend on the security requirements of your application. You can think of $_SESSION very similar to $_COOKIE: as a mechanism to provide state between page refreshes. In this context, the identity of your user. Your database should provide further authentication mechanisms. Things that may uniquely identify your user. A typical assumption is the IP address, but what happens if someones IP changes? User agent is another possibility but these arent very unique.

I would suggest taking a look at: http://php.net/manual/en/session.security.php

Brad
I think the IP address is good enough, specifically because most people are behind routers anyway, and that IP usually doesn't (in my experience) refresh unless the router is reset, usually along with some internal mechanism to refresh the IP. Also, even if the user's IP refreshing were a serious factor, all it would mean is that the user must log back in -- plus, in my own implementations, I usually make the session expire in around three or four hours.
Carson Myers
That is all very true. I was thinking more about mobile clients. If you are site is going to be accessed by a phone, if that person is on the go, there is a much higher chance of the IP changing. Still, this is typically a fairly small portion of web traffic for most people.
Brad
Also, if you are looking for seamless $_SESSION integration with your database, look at Zend_Auth component of the Zend Framework.
Brad
+7  A: 

It sounds like you've got the basics covered. However, if you're doing that all manually, then you are effectively just implementing your own $_SESSION, and not taking advantage of the fact that it can already do all that for you.

If you want to use a database to handle a session, you can override the default session handling with your own. Take a look at session_set_save_handler(). I do this in my apps.

class SessionHandler
{

    public function open($save_path, $session_name)
    {
        $this->sessionName = $session_name;
    return(true);
    }
    public function close() {
        //stuff
    }

    public function read($id) {
        $expiretime = date("Y-m-d H:i:s",time() - $this->maxLifeTime);
        $sql = "SELECT * FROM sessions where sessionid='".$this->db->escapeData($id)."' AND lastupdated>='".$expiretime."' LIMIT 1";
    $result = $this->db->query($sql);
        //etc.
    }

    //etc.

    public function setAsSessionHandler()
    {
    session_set_save_handler(
     array($this,'open'),
     array($this,'close'),
     array($this,'read'),
     array($this,'write'),
     array($this,'destroy'),
     array($this,'gc')
    );
    }
}

$sessionHandler = new SessionHandler();
$sessionHandler->setAsSessionHandler();

You can have all the functionality you just described that you've implemented yourself by using this, but still have the power of $_SESSION to do it for you.

For instance, if you wanted to add an IP check to see if the session is still valid before you start it, you can add that as part of the "open" function. If you wanted to write the session data to ten different databases (not that you would), you could accomplish this in the 'write' function.

Those functions are all used based on how you use $_SESSION, and by putting them into a simple class, you can manage how it works very effectively.

You'll see that the session id is a parameter passed to the read/write/destroy functions, and you'll still manage this the same way using your GUID generation routine. However, you could stick the guid generation and checks into this session manager class and simply have the open() function do them. Centralized, no muss, no fuss.

zombat