- URL: https://www.laruence.com/en/2012/01/10/2469.html
- Please include attribution when republishing.
Today I posted a question on my Weibo (Laruence):
When I'm interviewing, I often ask a question: "How do you set up a Session that expires after 30 minutes?" Don't think it looks simple — there's quite a lot of knowledge behind it. It's especially well-suited for testing whether the fundamentals are solid. Who wants to give it a try? Hehe.
Why do I ask this question? 1. I saw people on Twitter discussing this question, and 2. it occurred to me that I often ask this question, so.
Here, let me answer this question.
The first answer
So, the most common answer is: set the Session's expiration time, which is session.gc_maxlifetime. This answer is incorrect, for the following reasons:
1. First, PHP runs the session's gc with a certain probability, namely session.gc_probability and session.gc_divisor (for an introduction, see Deeply Understanding PHP Internals: A Small-Probability Notice in Session Gc ). The default values are 1 and 100 respectively, which means there's a 1% chance that PHP will run the Session gc when a Session starts. It can't be guaranteed that it will definitely expire at the 30-minute mark.
2. So what about setting a high-probability cleanup chance? That's still not right. Why? Because PHP uses the Session file's modification time (via stat) to determine whether it's expired. Increasing this probability would, on one hand, lower performance, and on the other, PHP uses "a single" file to store the Session variables associated with one session. Suppose I set a Session variable a=1 five minutes ago, and then set another Session variable b=2 five minutes later — then the modification time of this Session file is the time when b was added, so a can't be cleaned up at the 30-minute mark. Besides, there's also the third reason below.
3. By default (taking Linux as an example), PHP uses /tmp as the default storage directory for Sessions, and the manual also has the following description:
Note: If different scripts have different session.gc_maxlifetime values but share the same location for storing session data, then the script with the smallest value will clean up the data. In this case, use this directive together with session.save_path.
That is to say, if two applications both don't specify their own independent save_path, and one sets an expiration of 2 minutes (let's call it A), and another sets 30 minutes (let's call it B), then every time A's Session gc runs, it will simultaneously delete the Session files belonging to application B.
So, the first answer is not "completely strictly" correct.
The second answer
Another common answer is: set the expiration time of the Session ID's carrier, the Cookie, namely session.cookie_lifetime. This answer is also incorrect, for the following reason:
This expiration is only the Cookie expiring. Put another way, this part tests the difference between Cookies and Sessions. Session expiration is server-side expiration, whereas Cookie expiration is guaranteed by the client (browser). Even if you set a Cookie expiration, this only guarantees that a standard browser, when the time is up, won't send this Cookie (which contains the Session ID). But if you construct a request, you can still use the value of this Session ID.
The third answer
Use memcache, redis, etc. Okey, this answer is a correct one. However, obviously the interviewer would certainly then go on to ask you: what if you only use PHP?
The fourth answer
Of course, an interview isn't meant to stump you, but to test the thoroughness of your thinking. In this process, I'll point out these traps. So generally, the approach that fits the question is:
1. Set the Cookie expiration time to 30 minutes, and set the Session's lifetime to 30 minutes as well.
2. Add a Time stamp to each Session value yourself.
3. Before each access, check the timestamp.
Finally, someone asked: why set a 30-minute expiration time? Well, first, this is for the interview. Second, in a real usage scenario, for example — a coupon that expires after 30 minutes?
Thanks 🙂
Be First to Comment