会话和 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=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
为了清楚说明会发生什么(什么不会发生),我在不同的位置添加了一些 echo
s。上面代码的这个 sn-p 加上一些额外的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();
...
其中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 的一些信息。否则很清楚为什么找不到会话。
【参考方案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
必须设置为 1
或 On
以允许 PHP 使用 cookie。
如果服务器确实设置了 cookie,但您的浏览器不允许,请检查浏览器的 cookie 选项。还要检查php.ini
的session.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 重定向不起作用的主要内容,如果未能解决你的问题,请参考以下文章