离开页面时销毁PHP会话

9
我需要在用户离开特定页面时销毁一个会话。我在页面末尾使用session_destroy(),但这对我来说不可行,因为我的页面有分页。我的页面是:abc.php?page=1abc.php?page=2abc.php?page=3
因此,我需要在用户离开abc.php页面时销毁一个会话。如何做到不使用cookie呢?

4
可能是关闭/终止浏览器或选项卡时关闭会话的重复问题。 - Quentin
谢谢,兄弟。但这是一个ASP解决方案。我从中没有得到任何东西...我该怎么样才能让我的会话保持活动状态,直到用户访问我的abc.php页面。当用户离开abc.php时,只需销毁会话即可。 - riad
实际上,链接线程中的第一个答案才是正确的,而且根本不是特定于ASP的。 - deceze
@deceze - 是的,正确。但实际解决方案还远远不够。 - Valentin Flachsel
7个回答

23

当用户导航离开页面时执行某些操作是错误的做法,因为你不知道用户是否会导航到完全不同的页面(例如联系人.php),或者仅仅是转到abc.php的下一页。正如Borealid所指出的那样,你不能在没有JS的情况下完成这个操作。相反,你可以添加一个检查,看看用户是否来自abc.php:

首先,在你的abc.php文件中设置一个在$_SESSION数组中的唯一变量,作为标记表明用户已经浏览了这个页面:

$_SESSION['previous'] = basename($_SERVER['PHP_SELF']);

然后,在所有页面输出之前,添加以下内容以检查用户是否来自abc.php:

if (isset($_SESSION['previous'])) {
   if (basename($_SERVER['PHP_SELF']) != $_SESSION['previous']) {
        session_destroy();
        ### or alternatively, you can use this for specific variables:
        ### unset($_SESSION['varname']);
   }
}

只有当用户从abc.php进入并且当前页面不同的情况下,才会销毁会话(或特定变量)。

希望我已经清楚地解释了这点。


谢谢兄弟,它有效了...但是有一个问题。如果我不是从abc.php页面进入,会话存储不同的数据..无论如何,非常感谢你的解决方案... - riad
如果你想在会话数组中保留一些数据,而不是完全销毁它,那么你可以像Karthik指出的那样,只需使用unset($_SESSION['varname']); 即可取消设置在abc.php上的变量,而不是使用session_destroy() - Valentin Flachsel
不太用户友好。如果我在另一个标签页中打开了另一页,但仍然想同时继续使用 abc.php,该怎么办? - deceze
说实话,但在离开页面时销毁/取消会话变量的想法,而不使用JS,正是导致这个缺陷的根源。 - Valentin Flachsel

4

谢谢你的回答,兄弟。但是我的页面是为移动用户设计的,所以我不能使用JavaScript。这个问题只能通过PHP解决吗? - riad

1

我有类似的问题,但我的问题是在重新加载页面时,我希望已打印的变量被销毁。这是为我的Web设计课程的登录而做的错误反馈,用于检测用户输入错误的用户名或密码。我可以使错误显示出来,但如果我点击刷新页面,这些错误仍将存在。我发现只需在打印后将变量设置为空即可销毁它。看看我是怎么做的:

<p>To access my website please Login:</p>
<form name='login' action="./PHP_html/PHP/login.php" method='post'>
Username: <input type='text' name='username' /><div><?php print $_SESSION['baduser']; $_SESSION['baduser'] = "";?></div><br />
<div style="padding-left: 4px">Password: <input type='password' name='password' /><div><?php print $_SESSION['badpass']; $_SESSION['badpass'] = "";?></div></div>
<input type='submit' value='Login' /> or you can <a href="./Terms.php">Register</a>

我不知道这是否有所帮助,但对我有效。

此外,感谢所有在像这样的网站上发布帖子来帮助我们这些仍在学习的人。


0

我解决了这个问题。首先获取当前的URL,然后检查页面是否停留在当前的URL上。如果页面不在当前的URL上,则销毁会话。

$url = "http" . ((!empty($_SERVER['HTTPS'])) ? "s" : "") . "://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
$page_name="abc.php";      
if (!preg_match("/$page_name/",$url)) 
 {
  session_destroy();
 } 

但是这段代码应该在其他页面上使用。因为HTTP是无状态的进程,所以无法找到用户何时离开页面。


你实际上只需要使用 $_SERVER['REQUEST_URI'],因为那里就是文件名所在的位置。如果你有一个单独的 header.php 文件用于所有页面(这是常见的做法),你可以简单地使用我的解决方案,而不是在除了 abc.php 之外的所有页面中添加你的代码。 - Valentin Flachsel
1
如果你不把那段代码放到 abc.php 上,使用它就没有意义。我不知道这与 HTTP 无状态有什么关系。而且,你仍然面临着 FreekOne 回答中的同样问题,即会话数据即使在你没有离开 abc.php 的情况下也会被销毁。 - Lèse majesté

0

Borealid值得赞扬,他指出了最优雅的解决方案。

一种更加笨拙的解决方案是在页面上保留一个iframe,指向另一个“监视器”页面,该页面设置为每隔几秒钟刷新一次。这可以在不使用JavaScript的情况下完成:

<meta http-equiv="refresh" content="10">

每10秒刷新一次监控页面。当这个发生时,监控页面可以在服务器上的某个地方(数据库或文件)记录时间(覆盖以前记录的时间)和会话ID。

然后您需要创建一个cronjob,检查文件/数据库是否存在超过10 ~ 12秒的任何会话,并手动删除它们。会话数据通常存储在目录中(由您的PHP配置指定),文件名为sess_the-session-ID。您可以使用像这样的PHP函数:

function delete_session($sessId) {
    $sessionPath = session_save_path();
    // you'll want to change the directory separator if it's a windows server
    $sessFile = "$sessionPath/sess_$sessId";
    if (file_exists($sessFile) && unlink($sessFile)) return true;
    return false;
}

0
针对特定页面,您需要销毁会话,然后使用以下代码取消所有会话变量:

unset($_SESSION['varname']);

如果是整个网站,您可以使用以下代码:

session_destroy();


如果我在页面末尾取消或销毁变量,那么我就无法在第二或第三页abc.php?page=2或3中获取该值。因此,我必须使用会话直到用户离开我的abc.php页面。我该怎么做? - riad

0

无法可靠地确定用户何时从页面导航离开,这是不可能的。

最好的方法是利用 cookie 的工作原理。当启动会话时,您向客户端发送一个 cookie,该 cookie 标识客户端在每次访问中,并因此激活相应的会话。在后续访问中,由客户端发送此标识,并由客户端“忘记”其标识。

可以指示客户端仅发送某些页面的 cookie,并指示他在关闭浏览器时忘记 cookie(寿命为 0)。可以使用 session_set_cookie_params 进行设置。

除此之外,在不重要的页面上可以简单地忽略会话参数。当您假设客户端已离开时,可以在一段时间的不活动后删除会话(或其中某些值)。


这正是我想要的。问题是:如何在一段时间内没有活动后删除会话?类似于上面的方法,其中用户从哪里导航,但现在使用时间戳?比如:$_SESSION[]中的时间戳已经过了10分钟,所以它已经过期了? - Jens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接