Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/244.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在30分钟后使PHP会话过期?_Php_Session_Cookies - Fatal编程技术网

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

如何在30分钟后使PHP会话过期?,php,session,cookies,Php,Session,Cookies,我需要让一个会话保持活动状态30分钟,然后销毁它 这是否用于在设定的时间后注销用户?设置会话创建时间或注册时的到期时间,然后检查每个页面加载是否可以处理该问题 例如: 编辑:我觉得你是指别的东西 通过使用ini设置,您可以在特定的生命周期后废弃会话: 编辑: ini_set'session.gc_maxlifetime',60*30 您应该实现自己的会话超时。其他人提到的两种方案都不可靠。我会解释原因的 if (isSet($_SESSION['started'])){ if((mkti

我需要让一个会话保持活动状态30分钟,然后销毁它

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

例如:

编辑:我觉得你是指别的东西

通过使用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_最大生存期 session.gc_maxlifetime指定数据被视为“垃圾”并被清除的秒数。垃圾回收在会话启动期间发生

但是垃圾收集器的启动概率仅为除以。分别使用选项1和100的默认值,概率仅为1%

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

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

注意:如果您使用的是默认的基于文件的会话处理程序,那么文件系统必须随时跟踪访问时间。Windows FAT不是这样的,因此如果您使用的是FAT文件系统或任何其他无法使用atime跟踪的文件系统,那么您必须想出另一种方法来处理会话垃圾收集。自PHP4.2.3以来,它使用了mtime修改日期而不是atime。这样,您就不会在没有atime跟踪的文件系统中遇到问题

因此,由于会话数据最近未更新,因此在会话本身仍被视为有效时,会话数据文件可能会被删除

第二:

session.cookie\u生命周期 session.cookie\u lifetime指定发送到浏览器的cookie的生存期(以秒为单位)。[……]

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

结论/最佳解决方案:

<?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 lifetime
    ini_set("session.gc_maxlifetime", $timeout);

    // Set the session cookie to timout
    ini_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);
    }
}
最好的解决方案是实现自己的会话超时。使用一个简单的时间戳表示最后一个活动(即请求)的时间,并随每个请求更新:

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
使用每个请求更新会话数据也会更改会话文件的修改日期,以便垃圾收集器不会过早删除会话

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

注:

session.gc_maxlifetime应至少等于本例中此自定义过期处理程序1800的生存期; 如果要在活动30分钟后而不是启动后30分钟后使会话过期,还需要使用过期时间为+60*30的setcookie来保持会话cookie处于活动状态。 PHP会话在30分钟内到期的简单方法。 注意:如果您想更改时间,只需将30更改为您想要的时间,不要更改*60:这将给出分钟数

分钟:30*60 天数:n*24*60*60 n=天数

Login.php HomePage.php LogOut.php
使用如下函数实际上很容易。它使用数据库表名“sessions”和字段“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 succesfully
        if (count($rows) > 0) {
            $zeile = $rows[0];
            $time_past = $zeile['time'];
            if ( $timeout + $time_past < time() ) {
                //Time has expired
                session_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;
}

本文介绍了控制会话超时的几种方法:

IMHO第二个选项是一个很好的解决方案:

<?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 lifetime
    ini_set("session.gc_maxlifetime", $timeout);

    // Set the session cookie to timout
    ini_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);
    }
}

在会话中存储时间戳

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

<?php
session_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 timeout
    php_value session.cookie_lifetime 1800
    php_value session.gc_maxlifetime 1800
</IfModule>
使用会话_set _cookie _paramsfanceton进行此操作

必须在会话\u开始调用之前调用此函数

试试这个:

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

session_set_cookie_params($lifetime);

session_start();

有关详细信息,请参见:

请在应用程序中使用以下代码块 包括每个页面中加载的文件

$expiry = 1800 ;//session expiry required after 30 mins
    if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
        session_unset();
        session_destroy();
    }
    $_SESSION['LAST'] = time();
使用时间戳

<?php
if (!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作为替代。我使用一个DB函数来实现它,我称之为chk_lgn

Check login检查以查看他们是否登录,这样做时,它会将检查的日期时间戳设置为用户数据库行/列中最后一个活动的日期时间戳

我也在那里查时间。这对我来说暂时有效,因为我在每个页面上都使用这个函数


另外,我所见过的人中没有人建议使用纯DB解决方案。

只要存储当前时间,如果通过比较它超过30分钟,那么就销毁当前会话。

PHP如何处理会话对于初学者来说是相当混乱的。这可能有助于他们概述会话的工作方式:

这让我大开眼界,克里斯托弗·克莱默(Christopher Kramer)在2014年的

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


session.gc-maxlifetime可能是最好的方法。会话cookie生存期存在一些问题,最值得注意的是,它依赖客户端来强制执行。cookie生存期允许客户端清理无用/过期的cookie,它不会与任何安全相关的东西混淆。它是gc_maxlifetime还是gc maxlifetime。它同时支持下划线和连字符吗?如果您想检查非活动时间,如何更改它?换句话说,用户登录,只要他们继续使用该站点,它就不会将他们注销。但是,如果他们30分钟不活动,它会将他们注销?@Metropolis:使用类似于$_SESSION['LAST_ACTIVITY']的$_SESSION['CREATED']的$_SESSION['LAST_ACTIVITY'],其中存储用户最后一次活动的时间,但在每次请求时更新该值。现在,如果该时间与当前时间的差值大于1800秒,则会话的使用时间未超过30分钟。@Metropolis:session\u unset与$\u session=array的操作相同。@Gumbo-我有点困惑,您是否应该将代码与ini\u set'session.gc maxlifest',1800结合使用?否则,您的会话信息可能会在会话仍然有效时被破坏,至少如果ini设置是标准的24分钟。还是我遗漏了什么?@jeron:是的,你应该。但请注意,如果使用会话保存处理程序文件,则session.gc_maxlifetime取决于文件的上次修改日期。因此session.gc_maxlifetime应至少等于此自定义过期处理程序的生存时间。请注意,至少有两个设置对设置会话时间至关重要,可能还有三个。两个非常关键的参数是session.gc_maxlifetime和session.cookie_lifetime,其中0与一些长数字不同。为了完全、100%确定允许长时间运行,可能还需要设置session.save_路径,因为默认情况下存储会话文件的/tmp目录上的操作系统控制清理时间不同。我不明白您为什么要使会话过期。如果您担心用户未注销就离开了他的计算机,而未经授权的用户接管了他的计算机,那么您站点上的会话过期将不会阻止劫机者访问磁盘上受害者的文件。不清楚您在这里要问什么。你的意思是说你想实现一个硬的非活动超时,PHP会很高兴地让你使用一个超过session.gc_maxlife的会话,还是说你想将会话限制在30分钟之内,而不管它是否处于非活动状态?坦率地说,我认为对于这两个问题,这里接受的答案都是相当糟糕的建议——在这两种情况下,逻辑都应该使用自定义会话处理程序来实现。在MVC成为常态的今天,将逻辑和表示结合起来是不明智的。也许我缺少一些关于会话的基本内容,但如果会话是每30分钟就被操作系统摧毁一次?@仍然站着为自己说话[微笑]我认为MVC是一个讨厌的东西。即使项目很小,只有一个程序员,MVC是一个好主意吗?我觉得我应该在MVC模式下制作我自己的项目,或者解决问题,然后制作MVC,但是由于缺乏MVC的经验,这就成了一个思维障碍,我该如何制作这个MVC?以及从需要解决方案的初始目标/问题上分散注意力。@bsosca这里的许多人都应该这样做,你应该花更多的时间担心问题的解决方案,让OP来解决问题
提出一个你认为有效的问题-@Lode的答案完美地解释了为什么这个答案不可靠,不应该使用。你唯一的评估时间是在使用会话时,对吗?
<IfModule mod_php5.c>
    #Session timeout
    php_value session.cookie_lifetime 1800
    php_value session.gc_maxlifetime 1800
</IfModule>
$lifetime = strtotime('+30 minutes', 0);

session_set_cookie_params($lifetime);

session_start();
$expiry = 1800 ;//session expiry required after 30 mins
    if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
        session_unset();
        session_destroy();
    }
    $_SESSION['LAST'] = time();
<?php
if (!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>";
    }
}
?>
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");
    }
}