Session timeouts in PHP: best practices

Chad picture Chad · Aug 6, 2009 · Viewed 27.7k times · Source

What is the actual difference between session.gc_maxlifetime and session_cache_expire() ?

Suppose I want the users session to be invalid after 15 minutes of non-activity (and not 15 after it was first opened). Which one of these will help me there?

I also know I can do session_set_cookie_params() which can set the user's cookie to expire in some amount of time. However, the cookie expiring and the actual session expiring on the server side are not the same; does this also delete the session when the cookie has expired?

Another solution I have though of is simple $_SESSION['last_time'] = time() on every request, and comparing the session to the current time, deleting the session based on that. I was hoping there was a more "built-in" mechanism for handling this though.

Thanks.

Answer

Be_Open picture Be_Open · Oct 1, 2009

I spent some time looking for a good answer to how the php.ini server settings make sessions expire. I found a lot of info but it took a while to figure out why the settings work the way they do. If you're like me, this might be helpful to you:

Sessions are stored as cookies (files on the client's pc) or server side as files on the server. Both methods have advantages and disadvantages.

For the sessions stored on the server, three variables are used.

session.gc_probability session.gc_divisor session.gc_maxlifetime

(session.gc_probability/session.gc_divisor) produces the probability that the garbage collection routine will run. When the garbage collector runs, it checks for session files that haven't been accessed for at least session.gc_maxlifetime and deletes them.

This is all explained pretty well in forum posts (this one especially!) - But the following questions do come up:

1.) How is that probability applied? When does the server roll the dice?

A: The server rolls the dice every time session_start() is called during any active session on the server. So this means you should see the garbage collector run roughly once for every 100 times that session_start() is called if you have the default of session.gc_probability = 1 and session.gc_divisor = 100

2.) What happens on low volume servers?

A: When session_start() is called it FIRST refreshes the session and makes the session values available to you. This updates the time on your session file on the server. It THEN rolls the dice and if it wins (1 out of 100 chance) it calls the garbage collector. The garbage collector then checks all session id files and sees if there are any that are eligible for deletion.

So this means that if you are the only person on the server, your session will never go inactive and it will appear as though changing the settings have no effect. Let's say you change session.gc_maxlifetime to 10 and session.gc_probability to 100. This means there is a 100% chance the garbage collector will run and it will clear out any session files that haven't been accessed in the last 10 seconds.

If you're the only one on the server, your session will not be deleted. You need at least 1 other active session running for yours to go inactive.

So basically, on a low volume server or at a low volume time - it could be MUCH longer than session.gc_maxlifetime before the garbage collector actually runs and the sessions are actually deleted. And without knowing how this works, it may appear completely random to you.

3.) Why do they use the probability?

A: Performance. On a higher volume server you don't want the garbage collector running on every request of session_start(). It will slow down the server needlessly. So depending on your server volume, you may want to increase or decrease the probability that the garbage collector runs.

I hope that this ties things together for you. If you're like me and you tried session.gc_maxlifetime and it didn't seem to work (because you tried it out on a development server so as not to disturb anyone), then this post hopefully saved you some head scratching.

Good luck!