Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
327 views
in Technique[技术] by (71.8m points)

php - 30分钟后如何终止PHP会话?(How do I expire a PHP session after 30 minutes?)

我需要将会话保留30分钟,然后销毁它。

  ask by Tom translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You should implement a session timeout of your own.

(您应该自己实现会话超时。)

Both options mentioned by others ( session.gc_maxlifetime and session.cookie_lifetime ) are not reliable.

(其他人提到的两个选项( session.gc_maxlifetimesession.cookie_lifetime )都不可靠。)

I'll explain the reasons for that.

(我将解释其原因。)

First:

(第一:)

session.gc_maxlifetime

(session.gc_maxlifetime)
session.gc_maxlifetime specifies the number of seconds after which data will be seen as 'garbage' and cleaned up.

(session.gc_maxlifetime指定秒数,此后将数据视为“垃圾”并清除。)

Garbage collection occurs during session start.

(垃圾收集在会话开始期间发生。)

But the garbage collector is only started with a probability of session.gc_probability divided by session.gc_divisor .

(但是,垃圾回收器仅以session.gc_probability除以session.gc_divisor的概率启动。)

And using the default values for those options (1 and 100 respectively), the chance is only at 1%.

(使用这些选项的默认值(分别为1和100),机会只有1%。)

Well, you could simply adjust these values so that the garbage collector is started more often.

(好吧,您可以简单地调整这些值,以便更频繁地启动垃圾收集器。)

But when the garbage collector is started, it will check the validity for every registered session.

(但是,当启动垃圾收集器时,它将检查每个已注册会话的有效性。)

And that is cost-intensive.

(这是高成本的。)

Furthermore, when using PHP's default session.save_handler files, the session data is stored in files in a path specified in session.save_path .

(此外,当使用PHP的默认session.save_handler文件时,会话数据存储在session.save_path指定的路径中的文件中。)

With that session handler, the age of the session data is calculated on the file's last modification date and not the last access date:

(使用该会话处理程序,会话数据的期限是根据文件的最后修改日期而不是最后访问日期计算的:)

Note: If you are using the default file-based session handler, your filesystem must keep track of access times (atime).

(注意:如果使用默认的基于文件的会话处理程序,则文件系统必须跟踪访问时间(atime)。)

Windows FAT does not so you will have to come up with another way to handle garbage collecting your session if you are stuck with a FAT filesystem or any other filesystem where atime tracking is not available.

(Windows FAT并非如此,如果您卡在FAT文件系统或任何其他无法进行时间跟踪的文件系统上,则您将不得不想出另一种方式来处理会话的垃圾回收。)

Since PHP 4.2.3 it has used mtime (modified date) instead of atime.

(从PHP 4.2.3开始,它使用mtime(修改日期)代替atime。)

So, you won't have problems with filesystems where atime tracking is not available.

(因此,对于没有时间跟踪功能的文件系统,您不会有任何问题。)

So it additionally might occur that a session data file is deleted while the session itself is still considered as valid because the session data was not updated recently.

(因此,还可能会发生以下情况:删除会话数据文件,而由于会话数据最近未更新,因此会话本身仍被视为有效会话。)

And second:

(第二:)

session.cookie_lifetime

(session.cookie_lifetime)
session.cookie_lifetime specifies the lifetime of the cookie in seconds which is sent to the browser.

(session.cookie_lifetime指定发送到浏览器的cookie的生存时间(以秒为单位)。)

[…]

([…])

Yes, that's right.

(是的,这是正确的。)

This only affects the cookie lifetime and the session itself may still be valid.

(这只会影响cookie的生存期,会话本身可能仍然有效。)

But it's the server's task to invalidate a session, not the client.

(但是使会话无效是服务器的任务,而不是客户端。)

So this doesn't help anything.

(因此,这无济于事。)

In fact, having session.cookie_lifetime set to 0 would make the session's cookie a real session cookie that is only valid until the browser is closed.

(实际上,将session.cookie_lifetime设置为0将使会话的cookie成为真正的会话cookie ,该cookie仅在关闭浏览器之前才有效。)

Conclusion / best solution:

(结论/最佳解决方案:)

The best solution is to implement a session timeout of your own.

(最好的解决方案是实现自己的会话超时。)

Use a simple time stamp that denotes the time of the last activity (ie request) and update it with every request:

(使用一个简单的时间戳记来表示上一个活动(即请求)的时间,并随每个请求进行更新:)

if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
    // last request was more than 30 minutes ago
    session_unset();     // unset $_SESSION variable for the run-time 
    session_destroy();   // destroy session data in storage
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp

Updating the session data with every request also changes the session file's modification date so that the session is not removed by the garbage collector prematurely.

(在每个请求中更新会话数据也会更改会话文件的修改日期,以便垃圾收集器不会过早删除该会话。)

You can also use an additional time stamp to regenerate the session ID periodically to avoid attacks on sessions like session fixation :

(您还可以使用其他时间戳记来定期重新生成会话ID,以避免攻击会话,例如会话固定 :)

if (!isset($_SESSION['CREATED'])) {
    $_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
    // session started more than 30 minutes ago
    session_regenerate_id(true);    // change session ID for the current session and invalidate old session ID
    $_SESSION['CREATED'] = time();  // update creation time
}

Notes:

(笔记:)

  • session.gc_maxlifetime should be at least equal to the lifetime of this custom expiration handler (1800 in this example);

    (session.gc_maxlifetime应该至少等于此自定义过期处理程序的生存期(在此示例中为1800);)

  • if you want to expire the session after 30 minutes of activity instead of after 30 minutes since start , you'll also need to use setcookie with an expire of time()+60*30 to keep the session cookie active.

    (如果要在活动 30分钟后而不是从启动 30分钟后使会话过期,则还需要使用setcookie并使用time()+60*30的过期time()+60*30来保持会话cookie的活动。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...