PHP 中的会话超时:最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1236374/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Session timeouts in PHP: best practices
提问by Chad
What is the actual difference between session.gc_maxlifetimeand session_cache_expire()?
session.gc_maxlifetime和之间的实际区别是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?
假设我希望用户会话在 15 分钟非活动(而不是首次打开后 15 分钟)后无效。其中哪一项会帮助我呢?
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?
我也知道我可以做session_set_cookie_params()这可以将用户的 cookie 设置为在一段时间内过期。但是,cookie 过期和服务器端实际会话过期是不一样的;当 cookie 过期时,这是否也会删除会话?
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.
我想到的另一个解决方案是$_SESSION['last_time'] = time()对每个请求都很简单
,并将会话与当前时间进行比较,然后基于此删除会话。我希望有一个更“内置”的机制来处理这个问题。
Thanks.
谢谢。
回答by
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:
我花了一些时间寻找 php.ini 服务器设置如何使会话过期的好答案。我找到了很多信息,但花了一段时间才弄清楚为什么这些设置会按照它们的方式工作。如果你和我一样,这可能对你有帮助:
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.
会话存储为 cookie(客户端 PC 上的文件)或服务器端存储为服务器上的文件。这两种方法各有优缺点。
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 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.
(session.gc_probability/session.gc_divisor) 产生垃圾收集例程运行的概率。当垃圾收集器运行时,它会检查至少在 session.gc_maxlifetime 内未被访问的会话文件并删除它们。
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?
1.) 这个概率是如何应用的?服务器什么时候掷骰子?
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
答:在服务器上的任何活动会话期间,每次调用 session_start() 时,服务器都会掷骰子。所以这意味着如果你有 session.gc_probability = 1 和 session.gc_divisor = 100 的默认值,你应该看到垃圾收集器大约每 100 次调用 session_start() 运行一次
2.) What happens on low volume servers?
2.) 在低容量服务器上会发生什么?
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.
答:当 session_start() 被调用时,它首先刷新会话并使会话值对您可用。这会更新服务器上会话文件的时间。它然后掷骰子,如果它赢了(100 次机会中的 1 次),它会调用垃圾收集器。垃圾收集器然后检查所有会话 id 文件并查看是否有任何可以删除的文件。
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.
因此,这意味着如果您是服务器上唯一的人,您的会话将永远不会处于非活动状态,并且看起来好像更改设置没有任何效果。假设您将 session.gc_maxlifetime 更改为 10,将 session.gc_probability 更改为 100。这意味着垃圾收集器有 100% 的机会运行,并且会清除过去 10 秒内未访问的所有会话文件。
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.
如果您是服务器上唯一的一个,您的会话将不会被删除。您至少需要运行 1 个其他活动会话才能使您的会话处于非活动状态。
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.
所以基本上,在低容量服务器或低容量时间 - 在垃圾收集器实际运行和会话实际删除之前,它可能比 session.gc_maxlifetime 长得多。在不知道它是如何工作的情况下,它对您来说可能完全是随机的。
3.) Why do they use the probability?
3.) 为什么他们使用概率?
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.
一场表演。在更高容量的服务器上,您不希望垃圾收集器在 session_start() 的每个请求上运行。它会不必要地减慢服务器的速度。因此,根据您的服务器容量,您可能希望增加或减少垃圾收集器运行的概率。
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.
我希望这能为你把事情联系在一起。如果您像我一样尝试了 session.gc_maxlifetime 并且它似乎不起作用(因为您在开发服务器上尝试了它以免打扰任何人),那么这篇文章希望能让您免于头疼。
Good luck!
祝你好运!
回答by Glass Robot
Each time session_startis called the session files timestamp (if it exists) gets updated, which is used to calculated if session.gc_maxlifetime has been exceeded.
每次调用session_start 时,会话文件时间戳(如果存在)都会更新,用于计算 session.gc_maxlifetime 是否已超过。
More importantly you can't depend on a session to expire after session.gc_maxlifetime time has been exceeded.
更重要的是,在超过 session.gc_maxlifetime 时间后,您不能依赖会话过期。
PHP runs garbage collection on expired sessions after the current session is loaded and by using session.gc_probabilityand session.gc_divisorit calculates the probability that garbage collection will run. By default its a 1% probability.
PHP 在加载当前会话后对过期会话运行垃圾收集,并通过使用session.gc_probability和session.gc_divisor计算垃圾收集运行的概率。默认情况下,它的概率为 1%。
If you have a low number of visitors there is a probability that an inactive user could access a session that should have expired and been deleted. If this is important to you will need to store a timestamp in the session and calculate how log a user has been inactive.
如果您的访问者数量较少,则不活动的用户可能会访问本应已过期并被删除的会话。如果这对您很重要,您将需要在会话中存储时间戳并计算用户不活动的日志。
This example replaces session_startand enforces a timeout:
此示例替换session_start并强制执行超时:
function my_session_start($timeout = 1440) {
ini_set('session.gc_maxlifetime', $timeout);
session_start();
if (isset($_SESSION['timeout_idle']) && $_SESSION['timeout_idle'] < time()) {
session_destroy();
session_start();
session_regenerate_id();
$_SESSION = array();
}
$_SESSION['timeout_idle'] = time() + $timeout;
}
回答by Mark
session.gc_maxlifetimeis based off of the last time a session file was modified. So every time a session file is modified or a session_start() is called in a separate page, the countdown to gc_maxlifetime begins anew and the user stays "logged in". This is the value you are looking for. You can modify this through ini_set() in your php files, or edit php.ini if you have access to it
session.gc_maxlifetime基于上次修改会话文件的时间。因此,每次修改会话文件或在单独的页面中调用 session_start() 时,gc_maxlifetime 的倒计时都会重新开始并且用户保持“登录”状态。这就是您正在寻找的价值。您可以通过 php 文件中的 ini_set() 修改它,或者如果您有权访问它,则编辑 php.ini
session_cache_expire()only controls the HTTP "Expires" header. This header controls how long the downloaded page contents stay in the user's browser cache.
session_cache_expire()仅控制 HTTP “Expires”标头。此标头控制下载的页面内容在用户浏览器缓存中停留的时间。
回答by NXT
To check the current values, this code will be helpful:
要检查当前值,此代码将很有帮助:
$gc_maxlifetime = ini_get('session.gc_maxlifetime');
$gc_probability = ini_get('session.gc_probability');
$gc_divisor = ini_get('session.gc_divisor');

