6

我正在制作一个 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=truelogout=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();and ob_flush();,如此处所述。无论有没有这些,它都不起作用。

会话也存在不存储内容的问题。由于某种原因,我无法true在会话中存储。我的代码是否有问题导致它失败?

作为测试,我尝试echo在每个if/ifelse语句中编写一个命令。从那我发现脚本总是进入第三个语句 - 带有!($_SESSION['login']).

问题

到现在为止还挺好。这告诉我脚本能够检测到会话未设置。
剩下的两个问题是:

  • 为什么语句中的重定向不起作用,因为没有发生重定向,并且
  • 为什么不能首先设置会话。

任何建议将被认真考虑。


更新 1

为了清楚地说明会发生什么(以及什么不会发生),我echo在不同的位置添加了一些 s。上面的代码片段带有一些额外echo的 s:

...
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();
...

wherecutckilc16fm3h66k1amrrls96只是一个随机数,会话 id 是固定的,现在可以在页面刷新后再次检索存储的数据。这工作得很好;虽然仍然有点奇怪,但这是必要的。

现在我只需要标头重定向即可工作...

嗯,这闻起来像是被关闭的东西。会话和标头功能已更改。也许这是主机的一些 PHP 设置。阻止标头请求的东西。

待续...

更新 3 - 已解决

请看下面我的回答。

当我将文件更改为另一种编码格式时,文件开头会创建一些奇怪的符号,例如从 ANSI 到 UTF-8。创建的符号是,我在自己的编辑器中看不到它们。因为它们在 php 脚本前面,所以它们阻止了headerandsession_start()正常工作。为什么它们被创造出来对我来说仍然是一个谜。

4

4 回答 4

3

好的,让我们在这里列出您可以调试的所有内容,同时提及您已经做过的事情(以便其他人可以阅读):

  • 您是否安装了HTTP Header 之类的东西?然后您可以查看Location:标头是否已发送到您的浏览器。
  • 我想您没有收到任何错误消息,是吗?你定了error_reporting(E_ALL);吗?
  • 尝试var_dump()$_POST数组做。
  • 您是否还可以在浏览器中检查 cookie?我通常使用 Firefox web-developer 工具栏插件,它有一个菜单Cookie -> show cookie information。在那里您应该看到一个PHPSESSIDcookie(登录后)。如果没有,您的 URL 应该包含有关会话 ID 的一些信息(如下所示:)?PHPSESSID=514515ca274866b9f0b5b2520b6fcbb4。否则,PHP 找不到会话,因为它不知道哪个会话属于您。

如果这无助于检查是否设置了 cookie:

  • 再次打开您的标头插件,然后执行登录。检查服务器是否向您发送 cookie。这必须在Set-Cookie命令中完成。它可能看起来像这样:Set-Cookie: PHPSESSID=514515ca274866b9f0b5b2520b6fcbb4; path=/
  • 如果服务器没有设置 cookie,请检查php.ini. 必须有一个设置session.use_cookies = 1必须设置为1On允许 PHP 使用 cookie。
  • 如果服务器确实设置了 cookie,但您的浏览器不允许,请检查浏览器的 cookie 选项。还要检查php.ini. session.use_only_cookies = 0如果设置为1您禁止 PHP 在浏览器不接受 cookie 时使用 URL。出于安全原因,这通常是禁止的,因为人们将 URL 复制给朋友,然后这些朋友将接管登录的会话;)所以只需将其设置为0用于调试目的。
  • var_dump()的返回值session_start()。如果 PHP 无法正确启动会话,它将返回 false。
于 2012-07-14T20:19:36.463 回答
2

谜团在这里解决: 字节顺序标记

在此处输入图像描述

你会发现最好的答案:

https://stackoverflow.com/a/8028987/424004

于 2012-07-15T16:00:49.973 回答
1

尝试使用 session_id() 打印 PHPSESSID。如果你不断刷新,你会得到相同的输出吗?

如果不尝试设置 id: session_id('cutckilc16fm3h66k1amrrls96')

http://php.net/manual/en/function.session-id.php

它现在应该可以工作,但所有用户都使用相同的会话。

问题可能是这样的: PHP Session data not being saved

于 2012-07-14T22:27:22.753 回答
0

经过许多漫长的日日夜夜的测试、阅读和提问,并在参与者对这个问题的大力帮助下 -非常感谢您的努力!- 我慢慢地找到了这个问题的相当神秘的解决方案。
我找到了一个解决方案,但我仍然没有解释......

因此,如更新 2 中所述,我从@EmilF 的回答中发现会话 ID 不断变化。然后一个想法是怀疑服务器/主机问题。我联系了主机 - one.com - 一开始和我一样不明白为什么它不起作用。

但后来他告诉我,check.php文件开头有一些相当奇怪的符号。我无法在我自己的编辑器中看到它们。在我通过 one.com 提供的基于浏览器的 FileManager 软件访问文件之前,它们才可见。

问题及解决方案

文件的顶部如下所示:

<?
ob_start();
session_start();


if($_POST['password'] == 'xxx') {   // Correct password

    $_SESSION['login'] = true;
...

您可以在开头看到奇数符号。正如我所说,它们在我自己的编辑器 Notepad++中不可见,在常规记事本中也不可见。我把文件发给一个朋友检查,他在他的编辑 Coda 中也看不到它们。

这些符号当然会作为浏览器的输出。session_start()因此,这是在和之前发生的对浏览器的请求header(Location:...。因为这两个命令必须在任何浏览器请求之前,所以在这种情况下,它们现在在符号存在的情况下不起作用。

删除符号后,会话和header命令现在可以完美运行。

还是没有解释...

我不知道他们为什么在那里,但经过更多测试后,我发现了他们是如何到达那里的:

在 Notepad++ 中,我可以更改菜单中的编码格式。当我从 fx ANSI 更改为 UTF-8 时,出现了符号。在普通记事本中,我可以将“另存为”窗口中的选项另存为 UTF-8。并且符号也出现在这种情况下。

无论如何,当我通过直接从服务器获取文件的基于浏览器的编辑器查看代码时,我只能看到符号。无论是编辑器,它总是被创建。

我对此没有任何解释。这可能是另一个 SO 问题的好话题。

感谢所有试图帮助我的人。我在这里回答这个问题,因为这就是答案。但是所有帮助和调试技巧都非常感谢并且非常有帮助。

非常感谢,祝大家夏天愉快。

于 2012-07-15T15:50:40.293 回答