当使用ajax强制注销时,db表没有得到更新。

问题描述 投票:0回答:1

如标题所述,db表 trace_users 没有得到更新 30分钟无活动时 但它的更新时间是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['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'] : '';
    $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秒)内没有活动发生时,db表也应该得到更新。.

案例1(不工作) : 1800秒 (页面登出。数据库不更新) 案例2(工作) : 360秒 (页面登出。数据库得到更新)

session.gc_maxlifetime里面的值是1440(本地值) 1440(主值)

这是我试过的debugged。

在 "网络 "选项卡上,我得到的是 "请求方法"。获取 当设置了会话超时时 6分钟60分钟.

javascript php ajax post session-timeout
1个回答
2
投票

你需要给javascript传递一些永久的UID来识别用户的身份。即使会期过后.

为简化起见,我使用的是 user_name ,已经存在于你的代码中。但你也可以为每个用户分配一个UUID,这样就不能猜测另一个用户的名字,也不能修改他们的统计数据。


首先,你将通过 $_SESSION['user_name'] 从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完全结合在一个文件里是不好的做法。
  • 你的代码中有些地方不容易重现,我不得不从上下文中猜测(比如我猜测session已经设置好了,使用了jQuery,但是没有 <script src="...jquery.js">,有一个DB查询,但没有单独的SQL导入,可以快速尝试)。) 请大家阅读并运用所学知识,从 如何创建一个最小的、可复制的例子。 在你的下一个问题中,让更多的人能够或愿意帮助你解决这个问题。

1
投票

问题是你并没有改变任何东西来防止会话在N秒后过期,你只是将你的脚本编码成在这个时间后会销毁会话的方式。会话gc(garbage colector)会定期执行,并删除旧的会话,当发生这种情况时。$_SESSION['LAST_ACTIVITY'] 也会被删除。

你必须设法阻止gc删除会话,或者改变你的应用程序的逻辑。


1
投票

PHP进程不会无限期地坐着,也没有像Node.js服务器那样的循环程序结构,这就不允许你对session过期做出反应,因为它不是一个使其失效的进程,而是一个与session相关联的简单的时间戳,每次你试图使用它时都会检查。

我提供的解决方案是一个简单的脚本,每隔N分钟运行一次,将最后一个用户活动的时间戳(我认为这个时间戳是在该用户的请求中更新的)与到期时间(在你的情况下是30分钟)进行比较。你也可以将会话到期时间设置为30分钟,不过严格来说这不是必要的。如果时间差超过30分钟,你就更新表中用户的时间戳,如果必要的话,还可以使他们的会话无效。脚本可以通过cron或其替代品运行,并通过所有你需要执行检查的用户。


0
投票

有两件事你需要解决。

1). 将ajax请求设置为 async:false.

$.ajax({
    url: "/abc/mno.php",
      type: 'GET',
      async: false,   //  <---- ADDED ASYNC FALSE
      data: {
        action: 'logout'
    }, // Line A
     success: function(data) {
        console.log(data); // Line B
      },
     error: function(jqXHR, textStatus, errorThrown) {
         alert(textStatus);
       }
 });

2). 执行SQL查询后销毁会话。

<?php
session_start();     
if (isset($_GET['action']) && $_GET['action'] == "logout")
{
    !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'] : '';
    $stmt->bind_param('sss', $open, $write, $usname);
    $stmt->execute();
    session_destroy(); // destroy session data in storage <---- DESTORY AT THE END
}
?>
© www.soinside.com 2019 - 2024. All rights reserved.