提问者:小点点

会话在注销在线网站时不销毁,但可用于离线网站


我刚刚创建了一个包含登录页面的网站。当用户尝试登录时,我会根据数据库检查用户名和密码。如果两者都匹配,则启动会话并设置会话变量“id”和“uid”,如下所示:

$sql = "SELECT * FROM users WHERE uidUsers = ? OR emailUsers = ?";
        $stmt = mysqli_stmt_init($conn);
        if (!mysqli_stmt_prepare($stmt, $sql)) {
            header("Location: ../login.php?error=sqlerror");
            exit();
        }
        else {
            mysqli_stmt_bind_param($stmt, "ss", $mailuid, $mailuid);
            mysqli_stmt_execute($stmt);
            $result = mysqli_stmt_get_result($stmt);
            if ($row = mysqli_fetch_assoc($result)) {
                $pwdCheck = password_verify($password, $row['pwdUsers']);
                if ($pwdCheck == false) {
                    header("Location: ../login.php?error=wrongpwd&mail=".$mailuid);
                    exit();
                }
                elseif($pwdCheck == true) {
                    session_start();
                    $_SESSION['id'] = $row['idUsers'];
                    $_SESSION['uid'] = $row['uidUsers'];

                    header("Location: ../login.php?login=success");
                    exit();
                }
                else {
                    header("Location: ../login.php?error=wrongpwd");
                    exit();
                }
            }
            else {
                header("Location: ../login.php?error=nouser&mail=".$mailuid);
                exit();
            }
        }

在我的header.php文件中,它使用包括'header.php'链接到每个php页面;,我有显示登录/注册按钮的php代码(如果$_SESSION['id']是未设置)或注销按钮(如果设置了$_SESSION['id'])。我还在header.php页面开始了一个会话。这是header.php代码的样子:

session_start();

      if (isset($_SESSION['id'])) {

          echo 
          "<div id='logout-form'>
            <form action='includes/logout.inc.php' method='post'>
              <button type='submit' name='logout-submit'>Log Out</button>
            </form>
          </div>";

      }

      else {

          echo 
          "<div id='header-form'>
            <form action='includes/login.inc.php' method='post'>
              <button type='submit' name='login-button-header'>Log In</button>
            </form>
            <button id='signup-button'><a href='signup.php' class='header-signup'>Sign Up</a></button>
          </div>";

      }

      if (isset($_SESSION['id'])) {

          echo '<p class="greeting">Hello, <span class="greetingName">' . $_SESSION['uid'] . '</span></p>';

      } 

      date_default_timezone_set("America/Los_Angeles");

使用xampp,我离线连接到一个apache服务器。当点击我的网站时,会话对每一页都有效;如果我登录,它会记录我已经登录了我访问的每一页,这是应该的。然而,当我几天前发布我的网站时,它很难知道我是登录还是退出。我的网站网址是writingboxco.com如果你想看看我将要谈论的内容。当我登录时,它似乎知道我在每个网页上登录;我知道这一点,因为它在每个页面上提供了“你好,[用户名”的消息,这只发生在设置了$_SESSION['id']时。然而,当我点击“注销”并回到主页时,它仍然认为我登录了(因为我可能是,但我不知道为什么)。当单击“注销”按钮时,脚本“logout.inc.php”运行。在此文件中,我取消设置并销毁会话变量,如下所示:

session_start();
session_unset();
session_destroy();
$_SESSION = [];
header("Location: ../login.php");

此外,我只在网站的某些页面上登录。他们中的一些人注册我已经注销,而另一些人没有。我不知道为什么我在单击“注销”按钮后仍保持登录,这会破坏会话变量。当我的网站离线使用时,它工作得非常好;当我注销时,每个页面都会意识到这一点。然而,当在线时,它并不适用于每个页面。它仅适用于某些情况(某些页面保持登录状态,而某些页面正确注销)。此外,当我尝试使用备用帐户登录时,它会让我登录,但在某些页面上,“Hello[username]”消息仍然显示我刚注销的帐户的用户名,而不是我刚登录的帐户。你知道问题出在哪里吗?销毁会话变量失败是否有问题?可能是我应该看的其他代码吗?谢谢

UPDATE:我发现有一个错误消息,说明[28-Jan-2020 00:02:56UTC]PHP警告:session_start():无法发送会话缓存限制器-已发送的标头(输出开始于 /home1/writipe3/public_html/searchUsers.php: 1)在/######################################################################################################################################知道为什么会这样吗?


共1个答案

匿名用户

在PHP中销毁会话时,实际上并不是删除它。你只是把它标记为垃圾收集。物理删除发生在稍后。因此,为了确保会话被实际销毁,还必须删除传播会话id的会话cookie。

如果您查看session\u destory()文档中的示例1,您将看到一些关于如何执行此操作的示例代码:

<?php
// Initialize the session.
// If you are using session_name("something"), don't forget it now!
session_start();

// Unset all of the session variables.
$_SESSION = array();

// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}

// Finally, destroy the session.
session_destroy();

您可能会在实践中看到这一点的不同之处,因为不同的平台可以使用不同的垃圾收集方法来清理会话数据。例如,在大多数Windows系统上,这实际上可能会立即发生。已知一些基于Debian(Ubuntu)的系统使用在PHP之外的异步GC方法。

默认情况下,PHP通过概率算法实现这一点,其中向PHP发出的每个请求都将在给定的概率(通常约为1%的时间)内触发GC循环。因此,几乎在所有情况下,清理都是不确定的。