【发布时间】:2012-07-14 05:33:33
【问题描述】:
我正在制作一个 PHP 脚本check.php 来检查用户是否登录。只有一个用户,所以密码直接写在 php 代码中。 check.php 包含在每个相关页面的顶部(第 1 行),带有 <? include "check.php"; ?> 行。
代码
我已删除密码和域名。除此之外,以下是我的代码。 这里的重点是您在登录页面输入密码,然后通过 POST 将其发送到此脚本。
如果密码正确 xxx,会话login将存储true。
如果密码不正确,但设置了,这意味着用户输入了错误的内容,则任何现有会话都以session_destroy()结束,这意味着他已登录出去。
如果他到达一个页面但没有登录,则会话login应该为false或未设置,这意味着将使用} elseif(!($_SESSION['login'])) {。
最后,如果他单击 注销 按钮,他将被发送到该脚本,其 url 为:check.php?logout=true。 logout=true 应该被捕获在最后 elseif 语句中的 $_GET 中,并且会话应该在那里结束。
<?
ob_start();
session_start();
if($_POST['password'] == 'xxx') { // Correct password
$_SESSION['login'] = true;
header("Location: http://www.url.com/administration/index.php");
} elseif (isset($_POST['password'])) { // Wrong password
session_destroy();
header("Location: http://www.url.com/administration/login.php?true");
} elseif(!($_SESSION['login'])) { // Check at every page
header("Location: http://www.url.com/administration/login.php");
} elseif($_GET['logout']) { // Log out
session_destroy();
header("Location: http://www.url.com/");
}
ob_flush();
?>
问题
在每个 if 语句中,我都尝试重定向。我使用header("Location:...),但在任何情况下都不起作用。因为header 命令必须是根据规范发送到浏览器的第一个请求,所以我使用ob_start(); 和ob_flush(); 作为described here。无论有没有这些,它都不起作用。
还有一个问题是会话不会存储内容。由于某种原因,我无法在会话中存储true。我的代码是否有问题导致它失败?
作为测试,我尝试在每个 if / ifelse 语句中编写 echo 命令。从中我发现脚本总是进入第三条语句——带有!($_SESSION['login'])的语句。
问题
到目前为止一切顺利。这告诉我脚本能够检测到会话未设置。
剩下的两个问题是:
- 为什么语句中的重定向不起作用,因为没有发生重定向,并且
- 为什么一开始就无法设置会话。
我们将不胜感激。
更新 1
为了清楚说明会发生什么(什么不会发生),我在不同的位置添加了一些 echos。上面代码的这个 sn-p 加上一些额外的echos:
...
echo "Input: " . $_POST['password'];
echo "<br>Session before: " . $_SESSION['login'];
if($_POST['password'] == 'xxxx') { // Correct password
$_SESSION['login'] = true;
header("Location: http://www.url.com/administration/index.php");
echo "<br>Session after: " . $_SESSION['login'];
echo "<br>The first if works";
} ...
返回以下输出:
Input: xxxx
Session before:
Session after: 1
The first if works
(xxxx为密码,正确)
这是您正在登录的情况。您刚刚写了密码并已发送到check.php。
所以,我可以在这里看到它访问了第一个if。并且会话正确设置为true(或1)。当我刷新页面时,会话不再设置。不应该吗?
header 重定向显然没有任何作用。
更新 2
因此,多亏了下面@EmilF 的回答,我发现我的会话 ID(我可以使用echo session_id(); 将其打印到屏幕上)在每次页面移动或页面刷新时都会更改为一些新的随机数。我看起来好像存储在会话中的数据随后被遗忘了,因为新的会话 id 指向其他地方。
通过使用:
<?
session_id('cutckilc16fm3h66k1amrrls96');
session_start();
...
其中cutckilc16fm3h66k1amrrls96 只是一个随机数,会话ID 是固定的,现在可以在页面刷新后再次检索存储的数据。这工作得很好;虽然还是有点奇怪,但还是有必要的。
现在我只需要标头重定向即可工作...
嗯,这闻起来像是被关闭的东西。会话和标头功能已更改。也许这是主机的一些 PHP 设置。阻止标头请求的东西。
待续……
更新 3 - 已解决
请看下面我的回答。
当我将文件更改为另一种编码格式时,文件开头会创建一些奇怪的符号,例如从 ANSI 到 UTF-8。创建的符号是,我在自己的编辑器中看不到它们。因为它们在 php 脚本前面,所以它们会阻止 header 和 session_start() 正常工作。为什么它们被创造出来对我来说仍然是一个谜。
【问题讨论】:
-
您的 PHP 代码是否在 .php 文件中的 HTML 之前?
-
您是否安装了类似HTTPLiveHeader 的东西?然后您可以查看
Location:标头是否发送到您的浏览器。我想您没有收到任何错误消息,是吗?你设置error_reporting(E_ALL);了吗? -
@Aufziehvogel 我又读了一遍,我改变了看法。我第一次浏览它时,我认为它是为论坛而不是 SE 形成的。
-
尝试为 $_POST['password'] 数组执行 print_r。如果没有重定向工作,显然你的第一个 if 代码有问题。
-
@Steeven:好的,接下来的调试步骤:您是否也有一些东西可以在浏览器中检查 cookie?我通常使用 Firefox web-developer 工具栏插件,它有一个菜单 Cookie -> 显示 cookie 信息。在那里你应该看到一个 PHPSESSID cookie(登录后)。如果没有,您的 URL 应包含有关会话 ID 的一些信息。否则很清楚为什么找不到会话。