如何在30分钟后使PHP会话过期?

我需要让一个会话存活30分钟,然后摧毁它。

1157322 次浏览

这是在设定时间后注销用户吗?在注册时设置会话创建时间(或到期时间),然后在每个页面加载时检查是否可以处理。

例如:

$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());
// later
if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {unset($_SESSION['example']);}

编辑:我有一种感觉,你的意思是别的东西。

您可以使用#0 ini设置在特定生命周期后取消会话:

编辑:ini_set('session.gc_maxlifetime',60*30);

if (isSet($_SESSION['started'])){if((mktime() - $_SESSION['started'] - 60*30) > 0){//Logout, destroy session, etc.}}else {$_SESSION['started'] = mktime();}

您应该实现自己的会话超时。其他人提到的两个选项(session.gc_maxlifetimesession.cookie_lifetime)都不可靠。我将解释原因。

第一:

session.gc_maxlifetime
session.gc_maxlifetime指定数据被视为“垃圾”并被清理的秒数。垃圾收集发生在会话启动期间。

但是垃圾收集器仅以session.gc_probability除以session.gc_divisor的概率启动。使用这些选项的默认值(分别为1和100),几率仅为1%。

嗯,您可以简单地调整这些值,以便更频繁地启动垃圾收集器。但是当垃圾收集器启动时,它将检查每个注册会话的有效性。这是成本密集型的。

此外,当使用PHP的默认session.save_handler文件时,会话数据存储在session.save_path中指定的路径中的文件中。使用该会话处理程序,会话数据的年龄是根据文件的最后修改日期而不是最后访问日期计算的:

备注:如果您使用默认的基于文件的会话处理程序,您的文件系统必须跟踪访问时间(atime)。Windows FAT没有,所以如果您被困在FAT文件系统或任何其他不可用atime跟踪的文件系统中,您将不得不想出另一种方法来处理垃圾收集您的会话。自PHP 4.2.3以来,它使用mtime(修改日期)而不是atime。因此,您不会遇到不可用atime跟踪的文件系统的问题。

因此,还可能发生会话数据文件被删除,而会话本身仍然被认为是有效的,因为会话数据最近没有更新。

第二:

session.cookie_lifetime
session.cookie_lifetime以秒为单位指定发送到浏览器的cookie的生命周期。

是的,没错。这只会影响cookie的生命周期,会话本身可能仍然有效。但使会话无效是服务器的任务,而不是客户端。所以这没有任何帮助。事实上,将session.cookie_lifetime设置为0会使会话的cookie成为真正的会话cookie,仅在浏览器关闭之前有效。

结论/最佳解决方案:

最好的解决方案是自己实现会话超时。使用一个简单的时间戳来表示最后一个活动(即请求)的时间,并在每次请求时更新它:

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

使用每个请求更新会话数据还会更改会话文件的修改日期,以便垃圾收集器不会过早删除会话。

您还可以使用额外的时间戳定期重新生成会话ID,以避免对会话固定之类的会话的攻击:

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

备注:

  • session.gc_maxlifetime应至少等于此自定义过期处理程序的生命周期(本例中为1800);
  • 如果您想在活动的30分钟后而不是在自启动的30分钟后到期会话,您还需要使用setcookietime()+60*30的到期时间来保持会话cookie的活动状态。

PHP会话在30分钟内到期的简单方法。

注意:如果您想更改时间,只需将30更改为所需时间,不要更改*60:这将给出分钟数。


分钟:(30*60)
单位:(n*24*60*60)n=天数


Login.php

<?phpsession_start();?>
<html><form name="form1" method="post"><table><tr><td>Username</td><td><input type="text" name="text"></td></tr><tr><td>Password</td><td><input type="password" name="pwd"></td></tr><tr><td><input type="submit" value="SignIn" name="submit"></td></tr></table></form></html>
<?phpif (isset($_POST['submit'])) {$v1 = "FirstUser";$v2 = "MyPassword";$v3 = $_POST['text'];$v4 = $_POST['pwd'];if ($v1 == $v3 && $v2 == $v4) {$_SESSION['luser'] = $v1;$_SESSION['start'] = time(); // Taking now logged in time.// Ending a session in 30 minutes from the starting time.$_SESSION['expire'] = $_SESSION['start'] + (30 * 60);header('Location: http://localhost/somefolder/homepage.php');} else {echo "Please enter the username or password again!";}}?>

HomePage.php

<?phpsession_start();
if (!isset($_SESSION['luser'])) {echo "Please Login again";echo "<a href='http://localhost/somefolder/login.php'>Click Here to Login</a>";}else {$now = time(); // Checking the time now when home page starts.
if ($now > $_SESSION['expire']) {session_destroy();echo "Your session has expired! <a href='http://localhost/somefolder/login.php'>Login here</a>";}else { //Starting this else one [else1]?><!-- From here all HTML coding can be done --><html>Welcome<?phpecho $_SESSION['luser'];echo "<a href='http://localhost/somefolder/logout.php'>Log out</a>";?></html><?php}}?>

LogOut.php

<?phpsession_start();session_destroy();header('Location: http://localhost/somefolder/login.php');?>

使用如下函数实际上很容易。它使用数据库表名“会话”和字段“id”和“time”。

每次当用户再次访问你的网站或服务时,你应该调用这个函数来检查它的返回值是否为TRUE。如果它是FALSE,用户已经过期,会话将被销毁(注意:这个函数使用数据库类来连接和查询数据库,当然你也可以在你的函数或类似的东西中进行):

function session_timeout_ok() {global $db;$timeout = SESSION_TIMEOUT; //const, e.g. 6 * 60 for 6 minutes$ok = false;$session_id = session_id();$sql = "SELECT time FROM sessions WHERE session_id = '".$session_id."'";$rows = $db->query($sql);if ($rows === false) {//Timestamp could not be read$ok = FALSE;}else {//Timestamp was read succesfullyif (count($rows) > 0) {$zeile = $rows[0];$time_past = $zeile['time'];if ( $timeout + $time_past < time() ) {//Time has expiredsession_destroy();$sql = "DELETE FROM sessions WHERE session_id = '" . $session_id . "'";$affected = $db -> query($sql);$ok = FALSE;}else {//Time is okay$ok = TRUE;$sql = "UPDATE sessions SET time='" . time() . "' WHERE session_id = '" . $session_id . "'";$erg = $db -> query($sql);if ($erg == false) {//DB error}}}else {//Session is new, write it to database table sessions$sql = "INSERT INTO sessions(session_id,time) VALUES ('".$session_id."','".time()."')";$res = $db->query($sql);if ($res === FALSE) {//Database error$ok = false;}$ok = true;}return $ok;}return $ok;}

这篇文章展示了几种控制会话超时的方法:http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions

恕我直言,第二个选择是一个很好的解决方案:

<?php/**** Starts a session with a specific timeout and a specific GC probability.* @param int $timeout The number of seconds until it should time out.* @param int $probability The probablity, in int percentage, that the garbage*        collection routine will be triggered right now.* @param strint $cookie_domain The domain path for the cookie.*/function session_start_timeout($timeout=5, $probability=100, $cookie_domain='/') {// Set the max lifetimeini_set("session.gc_maxlifetime", $timeout);
// Set the session cookie to timoutini_set("session.cookie_lifetime", $timeout);
// Change the save path. Sessions stored in teh same path// all share the same lifetime; the lowest lifetime will be// used for all. Therefore, for this to work, the session// must be stored in a directory where only sessions sharing// it's lifetime are. Best to just dynamically create on.$seperator = strstr(strtoupper(substr(PHP_OS, 0, 3)), "WIN") ? "\\" : "/";$path = ini_get("session.save_path") . $seperator . "session_" . $timeout . "sec";if(!file_exists($path)) {if(!mkdir($path, 600)) {trigger_error("Failed to create session save path directory '$path'. Check permissions.", E_USER_ERROR);}}ini_set("session.save_path", $path);
// Set the chance to trigger the garbage collection.ini_set("session.gc_probability", $probability);ini_set("session.gc_divisor", 100); // Should always be 100
// Start the session!session_start();
// Renew the time left until this session times out.// If you skip this, the session will time out based// on the time when it was created, rather than when// it was last used.if(isset($_COOKIE[session_name()])) {setcookie(session_name(), $_COOKIE[session_name()], time() + $timeout, $cookie_domain);}}

在会话中存储时间戳


<?php$user = $_POST['user_name'];$pass = $_POST['user_pass'];
require ('db_connection.php');
// Hey, always escape input if necessary!$result = mysql_query(sprintf("SELECT * FROM accounts WHERE user_Name='%s' AND user_Pass='%s'", mysql_real_escape_string($user), mysql_real_escape_string($pass));
if( mysql_num_rows( $result ) > 0){$array = mysql_fetch_assoc($result);
session_start();$_SESSION['user_id'] = $user;$_SESSION['login_time'] = time();header("Location:loggedin.php");}else{header("Location:login.php");}?>

现在,检查时间戳是否在允许的时间窗口内(1800秒为30分钟)

<?phpsession_start();if( !isset( $_SESSION['user_id'] ) || time() - $_SESSION['login_time'] > 1800){header("Location:login.php");}else{// uncomment the next line to refresh the session, so it will expire after thirteen minutes of inactivity, and not thirteen minutes after login//$_SESSION['login_time'] = time();echo ( "this session is ". $_SESSION['user_id'] );//show rest of the page and all other content}?>

嗯,我知道上面的答案是正确的,但它们是在应用程序级别,为什么我们不简单地使用.htaccess文件来设置过期时间?

<IfModule mod_php5.c>#Session timeoutphp_value session.cookie_lifetime 1800php_value session.gc_maxlifetime 1800</IfModule>

使用session_set_cookie_params函数来执行此操作。

有必要在session_start()调用之前调用此函数。

试试这个:

$lifetime = strtotime('+30 minutes', 0);
session_set_cookie_params($lifetime);
session_start();

查看更多:http://php.net/manual/function.session-set-cookie-params.php

请在每个页面加载的包含文件中使用以下代码块。

$expiry = 1800 ;//session expiry required after 30 minsif (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {session_unset();session_destroy();}$_SESSION['LAST'] = time();

使用时间戳…

<?phpif (!isset($_SESSION)) {$session = session_start();}if ($session && !isset($_SESSION['login_time'])) {if ($session == 1) {$_SESSION['login_time']=time();echo "Login :".$_SESSION['login_time'];echo "<br>";$_SESSION['idle_time']=$_SESSION['login_time']+20;echo "Session Idle :".$_SESSION['idle_time'];echo "<br>";} else{$_SESSION['login_time']="";}} else {if (time()>$_SESSION['idle_time']){echo "Session Idle :".$_SESSION['idle_time'];echo "<br>";echo "Current :".time();echo "<br>";echo "Session Time Out";session_destroy();session_unset();} else {echo "Logged In<br>";}}?>

我用了20秒使用时间戳使会话过期

如果你需要30分钟加上1800(30分钟秒)…

使用本课程30分钟

class Session{public static function init(){ini_set('session.gc_maxlifetime', 1800) ;session_start();}public static function set($key, $val){$_SESSION[$key] =$val;}public static function get($key){if(isset($_SESSION[$key])){return $_SESSION[$key];} else{return false;}}public static function checkSession(){self::init();if(self::get("adminlogin")==false){self::destroy();header("Location:login.php");}}public static function checkLogin(){self::init();if(self::get("adminlogin")==true){header("Location:index.php");}}public static function destroy(){session_destroy();header("Location:login.php");}}

您可以直接使用数据库作为替代。我使用DB函数来完成我称之为chk_lgn。

检查登录检查以查看它们是否已登录,并且在这样做时,它将检查的日期时间戳设置为用户的数据库行/列中的最后一个活动状态。

我也在那里做时间检查。这对我来说暂时有效,因为我对每一页都使用这个功能。

P. S.我见过的人都没有提出过纯数据库解决方案。

只需存储当前时间,如果通过比较超过30分钟,则销毁当前会话。

PHP如何处理会话对于初学者来说是相当混乱的。这可能会通过概述会话的工作原理来帮助他们:会话如何工作(自定义会话处理程序)

这让我大开眼界,克里斯多夫·克莱默在2014年写道https://www.php.net/manual/en/session.configuration.php#115842

在基于debian的系统上,在运行时更改session.gc_maxlifetime没有实际效果。Debian通过设置session.gc_probability=0来禁用PHP自己的垃圾收集器。相反,它每30分钟运行一次cronwork(参见 /etc/cron.d/php5)来清理旧会话。这个cronwork基本上查看你的php.ini,并使用session.gc_maxlifetime的值来决定要清理哪些会话(参见 /usr/lib/php5/maxlifetime)。[…]

在这里您可以设置时间

$lifespan = 1800;ini_set('session.gc_maxlifetime', $lifespan); //default life time