我刚刚创建了一个包含登录页面的网站。当用户尝试登录时,我会根据数据库检查用户名和密码。如果两者都匹配,则启动会话并设置会话变量“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)在/######################################################################################################################################知道为什么会这样吗?
在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循环。因此,几乎在所有情况下,清理都是不确定的。