The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

User Sessions

OK now that I have finally gotten opinions from many on how to hash and protect users passwords I am ready to stir up discussion about users sessions. I am still pretty new to this and the one thing I know for sure is not to store a users password in a session. The biggest thing to me is validating the user with the sessions because I have been told on a shared server other users can tamper with these sessions. So feel free to give me your input on this topic.

Actually, I'm sure a search on this forum will turn up a lot about it. There's been many methods suggested for avoiding it, including storing the User Agent string in a session and/or storing the user's IP (or subnet).

As for making sure other users on the server don't tamper with your sessions, I don't think there's anything you can do about that. Do as much verification as you reasonably can on session data, but you can't really stop them in a shared hosting environment.

Actually, one method I saw once was as follows:
Concatenate every session variable value into one long string, hash it with a secret key, and store that in your session (when concatenating session variables, don't include this hash). Do this at the end of every script (to catch any/all updates you make during the script), and at the beginning of every script verify it. This gives you a nearly-foolproof method for catching any tampering of your session data.

Repeat the procedure to generate the checksum at the end of the script, and instead of checking it store it in $_SESSION['checksum'].

All that said, I don't think this is worth the effort. It's going to slow down your scripts, and to be perfectly frank I don't think you need to worry about other users in your shared hosting environment tampering with your sessions. It's just not worth it.

If you are worried about someone tampering with your sessions, then write your own session handling method that stores everything in your database. That way there are no files in the temp directory for anyone to mess with. This is the method I use, although I chose to do so a) for the experience and b) so that I could easily scale up to a giant, load-balanced server farm (albeit a very unlikely happenstance). My database-based sessions are at least as fast as PHP's file-based session (database reads are often faster than file system accesses, and unless the database is poorly designed are almost never slower), and they are more secure because no one can get to my temp files because I don't have any (although that's not a concern in my case since I'm on a virtual dedicated server).

how exactly do you go about database sessions? for example when a page loads how do I check the database to see if they are logged in? Do I have to perform a query that searches for there ip in the database or something? I have thought about learning to do database sessions but never found any good in depth tutorials on it.

1) Store their session id and a hashed flag consisting of their USER_AGENT and a simple salt.

2) if a session id is set, ie logged in, then at the top of every pageload - regenerate_session_id() so that everytime the user does something - they are given a new ID.

3) on pages that require login, make sure that they have a session ID, and the session flag matches the server user_agent, which should since a user's ip may change but they can't use different browsers with the same session. if its different, kill the whole session.

That's one way to do it. I built my session handler from scratch. Essentially I created a new database table, sessions, that does little more than store a session ID and link that to a user ID in the users table. Each time a page loads, I check if the session cookie exists, and if it does I look up the ID stored in it in my session table; if I find it, I load up that user's data into my user object. If the cookie doesn't exist or the session isn't in my table, the user isn't logged in and I redirect them to the login page.

I said "little more"; I also store a session expiration time so that I know when a session expires. Additionally, I store session variables in name=value pairs delineated by the '&' character (just like GET parameters in a URL); PHP has a handy function called parse_str for extrapolating data stored like that. Thus I have all the flexibility of PHP's sessions with the power of being fully database-based. And I have a deep understanding of what exactly sessions are and how exactly they work, more so than someone who merely reads just enough to know how to use $_SESSION.

1) Store their session id and a hashed flag consisting of their USER_AGENT and a simple salt.

2) if a session id is set, ie logged in, then at the top of every pageload - regenerate_session_id() so that everytime the user does something - they are given a new ID.

3) on pages that require login, make sure that they have a session ID, and the session flag matches the server user_agent, which should since a user's ip may change but they can't use different browsers with the same session. if its different, kill the whole session.

I think regenerating the session ID on every page load is perhaps a bit excessive, but if it's working for you then don't let me stop you. I'd do a little more than merely check for a session ID to verify that a user is logged in (like verify your hashed user agent string), but I'm sure you do do that and you merely neglected to mention so.

Edit:

Oh, you did mention that you do more to validate... I should have read your post more closely. I apologize.

I think regenerating the session ID on every page load is perhaps a bit excessive, but if it's working for you then don't let me stop you. I'd do a little more than merely check for a session ID to verify that a user is logged in (like verify your hashed user agent string), but I'm sure you do do that and you merely neglected to mention so.

#3 the session flag matches the server user_agent

maybe i worded it terribly, i don't blame you for not understanding me but thats what it said.

I only regenerate logged in users - which would alleviate as much load as possible since its an auction site and many will browse through without actually logging in.

One more note on regenerating session ID every time - I could be mistaken, but I believe PHP generates a new session file in your temp directory each time a new session ID is generated. Thus, a user who browses across 20 pages will have 20 files in your temp directory, since PHP only cleans up the directory every so often and only when such a file has expired (as per session.expire or whatever it's called). So this would be a very bad idea for a high-traffic site because you'd fill up your entire disk with these orphaned sessions. Should be fine for a low-traffic site, however, except that the increased file system access could slow you down.

One more note on regenerating session ID every time - I could be mistaken, but I believe PHP generates a new session file in your temp directory each time a new session ID is generated. Thus, a user who browses across 20 pages will have 20 files in your temp directory, since PHP only cleans up the directory every so often and only when such a file has expired (as per session.expire or whatever it's called). So this would be a very bad idea for a high-traffic site because you'd fill up your entire disk with these orphaned sessions. Should be fine for a low-traffic site, however, except that the increased file system access could slow you down.

I'm not sure on the technicalities of whether it creates a new file - or rewrites just the SESSID. But here's something to answer ur second half
5.1.0 Added the delete_old_session parameter.

Yea I plan to go strictly database driven with sessions and in the article I found it talks about how database sessions are a lot more friendly when it comes to large sites running on multiple servers.

I basically rewrote what I saw in some tutorials but changed a few things here and there to come up with the above class. Something I would like to know is would it be very hard to write a function similar to mysql_real_escape_string b/c I want this class to work with multiple database types.

Generating a new session id on each page load is a bad idea. It effectively prevents the user from having multiple windows open to the same site (using tabbed browsing for example). It's not needed either. To prevent session-hijacking, you just need to regenerate id when users privileges changes (eg. when a user logs in).

Generating a new session id on each page load is a bad idea. It effectively prevents the user from having multiple windows open to the same site (using tabbed browsing for example). It's not needed either. To prevent session-hijacking, you just need to regenerate id when users privileges changes (eg. when a user logs in).

Two comments Kayzio:
The first is more of a nitpick - your comments indicate that $LifeTime is a bool when it is in fact an int.

The second is especially relevant given your desire to make this compatible with more than one database: REPLACE is a MySQL-specific extension of the SQL standard and thus will not work on other databases. I'd suggest rewriting that as an UPDATE statement (in your Write method).