我正在创建一个PHP脚本check.php
来检查用户是否已登录。只有一个用户,因此密码直接写在php代码中。 check.php
包含在每个相关网页的顶部(第1行),其中包含<? include "check.php"; ?>
行。
我删除了密码和域名。除此之外,以下是我的代码。 这里的要点是您在登录页面输入密码,然后通过POST将其发送到此脚本。
如果密码正确 xxx,会话login
将存储true
。
如果密码不正确,但 设置,意味着用户键入错误,则任何现有会话都以session_destroy()
结束,这意味着他已退出。
如果他到达某个页面但未登录,则会话login
应为false或未设置,这意味着将使用} elseif(!($_SESSION['login'])) {
。
最后,如果他点击注销按钮,他会使用网址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
存储在会话中。我的代码是否存在问题导致其失败?
作为测试,我尝试在每个echo
/ if
语句中编写ifelse
命令。从那时我发现脚本总是进入第三个语句 - 带有!($_SESSION['login'])
的语句。
到目前为止一切顺利。这告诉我脚本能够检测到会话未设置 剩下的两个问题是:
任何建议都将受到赞赏。
为了清楚说明发生了什么(以及未发生的事情),我在不同的地点放了一些echo
。以上代码的这段代码包含一些额外的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
重定向显然没有做任何事情。
所以,感谢下面@EmilF的答案,我发现我的会话ID - 我可以用echo session_id();
打印到屏幕 - 在每次页面转换或页面刷新时都会更改为一些新的随机数。我看起来好像存储在会话中的数据被遗忘了,因为新的会话ID指向其他地方。
使用:
<?
session_id('cutckilc16fm3h66k1amrrls96');
session_start();
...
其中cutckilc16fm3h66k1amrrls96
只是一个随机数,会话ID是固定的,现在可以在页面刷新后再次检索存储的数据。这非常有效;虽然有点奇怪但是有必要。
现在我只需要标题重定向工作......
嗯,这闻起来像被关闭的东西。会话和标头功能已更改。也许这是来自主机的一些PHP设置。阻止标头请求的东西。继续......
请参阅下面的答案。
当我将文件更改为另一种编码格式时,在文件的开头会创建一些奇怪的符号,例如:从ANSI到UTF-8。创建的符号是
,我在自己的编辑器中看不到它们。因为它们位于php脚本的前面,所以它们会阻止header
和session_start()
正常工作。为什么他们被创造出来对我来说仍然是一个谜。
答案 0 :(得分:3)
Okey,让我们列出你可以在这里调试的所有内容,并提及你已经做过的事情(所以其他人可以阅读):
Location:
标头发送到您的浏览器。error_reporting(E_ALL);
?var_dump()
数组执行$_POST
。PHPSESSID
cookie(登录后)。如果没有,您的网址应包含有关会话ID的一些信息(如下所示:?PHPSESSID=514515ca274866b9f0b5b2520b6fcbb4
)。否则,PHP无法找到会话,因为它不知道哪个会话属于您。如果这无助于检查cookie是否已设置:
Set-Cookie
命令中完成。它可能如下所示:Set-Cookie: PHPSESSID=514515ca274866b9f0b5b2520b6fcbb4; path=/
php.ini
中的设置。必须设置session.use_cookies = 1
设置,必须设置为1
或On
才能允许PHP使用Cookie。php.ini
的{{1}}设置。如果设置为session.use_only_cookies = 0
,则禁止PHP使用URL,如果浏览器不接受cookie。出于安全原因,这通常是被禁止的,因为人们将URL复制到朋友,然后这些朋友将接管已登录的会话;)因此,只需将其设置为1
以进行调试。0
var_dump()
的返回值。如果PHP无法正确启动会话,它将返回false。答案 1 :(得分:2)
答案 2 :(得分:1)
尝试使用session_id()打印PHPSESSID。如果你保持清爽,你会得到相同的输出吗?
如果没有尝试设置id:session_id('cutckilc16fm3h66k1amrrls96')
http://php.net/manual/en/function.session-id.php
现在应该可以使用,但所有用户使用相同的会话。
问题可能是这样的: PHP Session data not being saved
答案 3 :(得分: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问题,这可能是一个很好的主题。
感谢所有试图帮助我的人。我在这里回答这个问题,因为这个是的答案。但是所有的帮助和调试技巧都非常受欢迎并且非常有用。
非常感谢,祝大家夏天好。