首页 > 解决方案 > 使用ajax强制注销时数据库表未更新

问题描述

如标题中所述,当 30 分钟内没有任何活动发生时,数据库表trace_users不会更新,但在 6 分钟内会更新。

以下代码(JS 和 PHP)位于同一个 php 文件mno.php中。

我通过let lastActivity = <?php echo time(); ?> ; 下面脚本中的这一行存储用户的最后一个活动。

<?php
session_start();     
if (isset($_GET['action']) && $_GET['action'] == "logout")
{
    session_destroy(); // destroy session data in storage
    !isset($_SESSION['admin']);
    $open = "false";
    $write = "0";
    $stmt = $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
    $usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';
    $stmt->bind_param('sss', $open, $write, $usname);
    $stmt->execute();
}
?>
<script>
    jQuery(document).ready(function($) {

        let lastActivity = <?php echo time(); ?> ;  // storing last activity of user

        let now = <?php echo time(); ?> ;

        let logoutAfter = 360;

        let timer = setInterval(function() {
            now++;
            let delta = now - lastActivity;
            console.log(delta);
            if (delta > logoutAfter) {
                clearInterval(timer);
                //DO AJAX REQUEST TO close.php
                $.ajax({
                    url: "/abc/mno.php",
                    type: 'GET',
                    data: {
                        action: 'logout'
                    }, // Line A
                    success: function(data) {
                        console.log(data); // Line B
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        alert(textStatus);
                    }
                });
            }
        }, 1000);
    }); 
</script>

问题陈述:

我想知道我应该在上面的代码中进行哪些更改,以便在 30 分钟(1800 秒)内没有任何活动发生时,数据库表也应该得到更新

Case1(不工作): 1800 秒(页面注销,数据库不更新
Case2(工作): 360 秒(页面注销,数据库更新

session.gc_maxlifetime 里面的值是 1440(Local Value) 1440(Master Value)

这是我尝试过/调试过的:

在网络选项卡上,当会话超时设置为6 mins60 mins时,我得到了 Request Method GET

标签: javascriptphpajaxpostsession-timeout

解决方案


您需要向 javascript 传递某种永久 UID,即使在会话过期后也能识别用户。

为了简化起见,我正在使用user_name您的代码中已经存在的那个。但是您也可以为每个用户分配一个 UUID,这样就无法猜测另一个用户的名称,也无法修改他们的统计信息。


首先,您将把$_SESSION['user_name']from PHP 传递给 JS 闭包。

let userName = "<?php echo $_SESSION['user_name']; ?>";  // don't forget to wrap the JS string value in quotes or apostrophes

然后,您将在 AJAX 请求负载中传递它。

data: {
    action: 'logout',
    user_name: userName  // added param
},

最后,您将覆盖发送到 DB 的值(如果它与有效负载一起发送)

$usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';  // original line
if (isset($_GET['user_name']) && !empty($_GET['user_name'])) {
    $usname = $_GET['user_name'];
}
$stmt->bind_param('sss', $open, $write, $usname);  // original line

完整更新代码:

<?php
if (isset($_GET['action']) && $_GET['action'] == "logout")
{
    session_destroy(); // destroy session data in storage
    !isset($_SESSION['pageadmin']);
    $open = "false";
    $write = "0";
    $stmt = $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
    $usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';
    if (isset($_GET['user_name']) && !empty($_GET['user_name'])) {
        $usname = $_GET['user_name'];
    }
    $stmt->bind_param('sss', $open, $write, $usname);
    $stmt->execute();
}
?>
<script>
    jQuery(document).ready(function($) {

        let lastActivity = <?php echo time(); ?> ;  // storing last activity of user

        let now = <?php echo time(); ?> ;

        let logoutAfter = 10;

        let userName = "<?php echo $_SESSION['user_name']; ?>";

        let timer = setInterval(function() {
            now++;
            let delta = now - lastActivity;
            console.log(delta);
            if (delta > logoutAfter) {
                clearInterval(timer);
                //DO AJAX REQUEST TO close.php
                $.ajax({
                    url: "/abc/mno.php",
                    type: 'GET',
                    data: {
                        action: 'logout',
                        user_name: userName
                    }, // Line A
                    success: function(data) {
                        console.log(data); // Line B
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        alert(textStatus);
                    }
                });
            }
        }, 1000);
    }); 
</script>

最后的几点说明:

  • 将 PHP、HTML 和 JS 完全组合在一个文件中是一种不好的做法。
  • 您的代码的某些部分不容易重现,我不得不从上下文中猜测(例如,我猜想会话已经设置,使用了 jQuery 但没有<script src="...jquery.js">,有一个 DB 查询但没有单独的 SQL 导入来尝试它迅速地)。请在您的下一个问题中阅读并应用如何创建一个最小的、可重现的示例中的知识,以便更多的人能够或愿意帮助您。

推荐阅读