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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/520237/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 22:58:18  来源:igfitidea点击:

How do I expire a PHP session after 30 minutes?

phpsessioncookies

提问by Tom

I need to keep a session alive for 30 minutes and then destroy it.

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

回答by Gumbo

You should implement a session timeout of your own. Both options mentioned by others (session.gc_maxlifetimeand session.cookie_lifetime) are not reliable. I'll explain the reasons for that.

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

First:

第一的:

session.gc_maxlifetime
session.gc_maxlifetimespecifies the number of seconds after which data will be seen as 'garbage' and cleaned up. Garbage collection occurs during session start.

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

But the garbage collector is only started with a probability of session.gc_probabilitydivided by session.gc_divisor. And using the default values for those options (1 and 100 respectively), the chance is only at 1%.

但是垃圾收集器仅以session.gc_probability除以session.gc_divisor的概率启动。使用这些选项的默认值(分别为 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_handlerfiles, the session data is stored in files in a path specified in 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:

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

Note:If you are using the default file-based session handler, your filesystem must keep track of access times (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. Since PHP 4.2.3 it has used mtime (modified date) instead of atime. So, you won't have problems with filesystems where atime tracking is not available.

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

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_lifetimespecifies the lifetime of the cookie in seconds which is sent to the browser. […]

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

Yes, that's right. This only affects the cookie lifetime and the session itself may still be valid. 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_lifetimeset to 0would make the session's cookie a real session cookiethat is only valid until the browser is closed.

恩,那就对了。这只会影响 cookie 的生命周期,会话本身可能仍然有效。但是使会话无效是服务器的任务,而不是客户端。所以这没有任何帮助。事实上,将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 (i.e. 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_maxlifetimeshould be at least equal to the lifetime of this custom expiration handler (1800 in this example);
  • if you want to expire the session after 30 minutes of activityinstead of after 30 minutes since start, you'll also need to use setcookiewith an expire of time()+60*30to keep the session cookie active.
  • session.gc_maxlifetime应该至少等于这个自定义过期处理程序的生命周期(在这个例子中是 1800);
  • 如果您想在活动30 分钟后而不是自 start后 30 分钟后使会话过期,您还需要使用setcookieexpire oftime()+60*30来保持会话 cookie 处于活动状态。

回答by Rafee

Simple way of PHP session expiry in 30 minutes.

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

Note : if you want to change the time, just change the 30 with your desired time and do not change * 60: this will gives the minutes.

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



In minutes : (30 * 60)
In days : (n * 24 * 60 * 60 ) n = no of days

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



Login.php

登录.php

<?php
    session_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>

<?php
    if (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

主页.php

<?php
    session_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
                <?php
                    echo $_SESSION['luser'];
                    echo "<a href='http://localhost/somefolder/logout.php'>Log out</a>";
                ?>
            </html>
<?php
        }
    }
?>

LogOut.php

登出.php

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

回答by Ross

Is this to log the user out after a set time? Setting the session creation time (or an expiry time) when it is registered, and then checking that on each page load could handle that.

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

E.g.:

例如:

$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());

// later

if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {
    unset($_SESSION['example']);
}

Edit:I've got a feeling you mean something else though.

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

You can scrap sessions after a certain lifespan by using the session.gc_maxlifetimeini setting:

您可以使用session.gc_maxlifetimeini 设置在特定生命周期后废弃会话:

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

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

回答by Pablo Pazos

This post shows a couple of ways of controlling the session timeout: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions

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

IMHO the second option is a nice solution:

恕我直言,第二个选项是一个不错的解决方案:

<?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);
    }
}

回答by Touqeer Shafi

Well i understand the aboves answers are correct but they are on application level, why don't we simply use .htaccessfile to set the expire time ?

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

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

回答by Wallace Maxters

Use the session_set_cookie_paramsfunciton for make this.

使用功能session_set_cookie_params来制作这个。

Is necessary calling this function before session_start()call.

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

Try this:

尝试这个:

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

session_set_cookie_params($lifetime);

session_start();

See more in: http://php.net/manual/function.session-set-cookie-params.php

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

回答by middus

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

回答by Torsten Barthel

It's actually easy with a function like the following. It uses database table name 'sessions' with fields 'id' and 'time'.

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

Every time when the user visits your site or service again you should invoke this function to check if its return value is TRUE. If it's FALSE the user has expired and the session will be destroyed (Note: This function uses a database class to connect and query the database, of course you could also do it inside your function or something like that):

每次当用户再次访问您的站点或服务时,您都应该调用此函数来检查其返回值是否为 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;
}

回答by Alpesh Rathod

Store a timestamp in the session

在会话中存储时间戳



<?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");
}
?>

Now, Check if the timestamp is within the allowed time window (1800 seconds is 30 minutes)

现在,检查时间戳是否在允许的时间窗口内(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
}
?>

回答by lnepal

Please use following block of code in your include file which loaded in every pages.

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

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