会话和 php 重定向不起作用

Posted

技术标签:

【中文标题】会话和 php 重定向不起作用【英文标题】:Sessions and php redirect doesn't work 【发布时间】: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=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();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 脚本前面,所以它们会阻止 headersession_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 的一些信息。否则很清楚为什么找不到会话。 【参考方案1】:

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

您是否安装了类似HTTP Header 的东西?然后您可以查看Location: 标头是否发送到您的浏览器。 我想您没有收到任何错误消息,是吗?你设置error_reporting(E_ALL);了吗? 尝试为$_POST 数组执行var_dump()。 您是否还可以在浏览器中检查 cookie?我通常使用 Firefox web-developer 工具栏插件,它有一个菜单 Cookie -> 显示 cookie 信息。在那里你应该看到一个PHPSESSID cookie(登录后)。如果没有,您的 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.inisession.use_only_cookies = 0 设置。如果设置为1,如果浏览器不接受 cookie,您将禁止 PHP 使用 URL。出于安全原因,这通常是被禁止的,因为人们将 URL 复制给朋友,然后这些朋友将接管登录的会话;)因此只需将其设置为 0 以进行调试。 var_dump()session_start() 的返回值。如果 PHP 无法正确启动会话,它将返回 false。

【讨论】:

为什么会这样:"If non of the redirects are working, obviously your first if statement has something wrong in the code."? 好问题。以为我几个小时前就明白了,但现在我无法通过。刚刚从 redelman431 复制它。我会删除它。 php.ini 似乎已被弃用。我使用了 phpinfo()。正如你所说的,我发现:session.use_cookies 开启,session.use_only_cookies 关闭。 elseif 语句是否不会遍历每个条件,直到一个条件为真? @redelman431。 if 和 elseif 只测试自己的条件。如果if 为真,则不执行以下 elseif。它只是一个优先测试的语句列表,直到其中一个为真。【参考方案2】:

谜团在这里解开: Byte Order Mark

您将找到的最佳答案:

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

【讨论】:

【参考方案3】:

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

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

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

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

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

【讨论】:

好吧,这成功了:) 至少解决了我一半的问题。即使在页面移动和刷新时,会话值现在也会被存储。似乎每次都更改了会话 ID,现在已阻止。非常感谢!现在我只需要标题就可以工作了... 但是,如果所有人都获得相同的 session_id,您会不会在使用当前肮脏的解决方案时遇到麻烦?我的意思是,这意味着如果你已经登录并且我访问了你的页面,我会得到相同的 session_id,然后我也登录了。 是的,这很危险.. 在session_start () 之前使用ini_set ('session.use_only_cookies', 1); 并重试.. @Steeven 请确保您的浏览器启用了cookie,嗯【参考方案4】:

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

因此,如更新 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 问题的好话题。

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

非常感谢,祝大家暑假愉快。

【讨论】:

以上是关于会话和 php 重定向不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为啥页面重定向在 php 中不起作用

PHP标头重定向不起作用并停留在login.php上

通过非 PHP 扩展访问时,PHP 会话不起作用

PHP在登录/退出时重新生成会话ID不起作用

PHP重定向不起作用

在没有 index.php 的情况下,codeigniter 重定向不起作用?