【发布时间】:2010-10-07 13:34:04
【问题描述】:
全部,
提前抱歉 - 我不是 PHP 专家,也不是设计模式知识,所以这个问题可能有点基础......
无论如何,我正在开发一个需要登录的网络应用程序。
我的计划是这样的:
index.php:此页面将包含一个简单的表单,允许用户输入用户名和密码。该表单会将输入发布到...
login.php:此页面将接收来自 index.php 的输入,并根据数据库检查这些凭据。如果缺少任何输入,或者凭据检查失败,则 php 脚本将 REDIRECT 用户返回 index.php,使用:
header('Location: http://www.mydomain.com/index.php');
如果凭据有效,则 login.php 创建会话以建立用户的身份验证状态:
session_start();
$_SESSION['authenticated'] = true;
然后,它确定用户拥有什么访问类型。如果他具有“1 级”访问权限,脚本将使用以下命令将用户重定向到 level1.php:
header('Location: http://www.mydomain.com/level1.php');
如果用户具有“2 级”访问权限,脚本将使用以下命令将用户重定向到 level2.php:
header('Location: http://www.mydomain.com/level2.php');
最后,当到达 level1.php 或 level2.php 时,他们做的第一件事就是检查会话。如果用户未通过身份验证,则将他重定向回 index.php:
session_start();
if (!isset($_SESSION['authenticated']) {
header('Location: http://www.mydomain.com/index.php');
} else {
// proceed to display the page
}
在 level1.php 和 level2.php 中进行此检查将阻止用户直接访问该页面,而无需登录。
我的第一个问题是:这个简单的逻辑第一次失败 - 当达到 level1.php 时,“isset($_SESSION['authenticated']”ALWAYS 返回 false,所以用户总是被重定向回 index.php。如果他第二次输入完全相同的凭据,该过程将正常运行。
简而言之,由于我不明白的原因,level1.php 似乎找不到 login.php 设置的会话 - 我假设是因为重定向。换句话说,对 level1.php 的检查似乎会失败,直到/除非对客户端的浏览器进行往返。
由于每个需要登录的站点都已经解决了这个问题,这不应该是一个新的挑战,它们应该是一个非常成熟的模式。我该如何处理?
一个相关问题...我以前在这里看到过类似的问题,大多数答案通常涉及一个解决方案,在该解决方案中,页面正在回发给自己。这似乎有点奇怪 - 理想情况下,我想让每个 PHP 页面执行特定的工作:
- index.php - 显示要捕获的表单 凭据,然后将它们发布到 登录.php
- login.php - 评估用户的 凭据,然后将它们定向到 合适的页面
- level1.php & level2.php - 显示 适当的内容
这是一个有缺陷的设置吗?如果是这样,更好的设置是什么?
通常 - 如果一个页面建立会话,然后将用户重定向到另一个页面 - 有什么方法可以让第二个页面读取会话?
维基百科上有一个关于发布/重定向/获取的精彩页面:
http://en.wikipedia.org/wiki/Post/Redirect/Get
但这对我来说有点概念性 - 我希望通过对特定页面的引用来解释它:
例如“页面 A”上的表单将数据发布到“页面 B”,“页面 B”将用户重定向到“页面 C”,等等......
而且,如果在使用重定向时无法识别会话,我不明白它是如何通过会话实现的。
非常感谢您提供任何建议和见解。
[更新]
感谢 Matt Ball 的评论,我已经完善了这个问题:
login.php 正在设置会话并将用户重定向到下一个屏幕:
session_start();
$_SESSION['authenticated'] = true;
header('Location: http://www.mydomain.com/level1.php');
但是,当 level1.php 检查该会话时,“已验证”是未设置:
session_start();
echo (isset($_SESSION['authenticated']); // returns false
但是,如果我更改 login.php 以使标头重定向到 RELATIVE 网址而不是绝对网址:
session_start();
$_SESSION['authenticated'] = true;
header('Location: level1.php');
然后,level1.php 像我预期的那样工作:
session_start();
echo (isset($_SESSION['authenticated']); // now returns true
我不明白为什么相对 URL 会有所不同,但确实如此。所以,至少我眼前的问题得到了解决。
非常感谢所有评论的人!
干杯, 马特·斯图勒
【问题讨论】:
-
关于会话问题的黑暗中的一枪:您是否在 level1.php 中调用了
session_start();?另一件事:出于安全原因,您不仅应该检查会话在 level1...x.php 中是否有效,还要检查用户的级别是否足够。否则,Level1 用户可以登录,然后手动调用 level2.php。 -
您应该使用 Firebug+FireCookie 之类的工具来检查 PHPSESSID cookie 是否在 login.php 发送其标头时实际设置,并且之后它们也存在。
-
我认为您需要在用户登录后重定向回之前启动会话
-
@matt:会话肯定被重定向识别。 HTTP 重定向只是从服务器到浏览器的一条消息,它说:“嘿,浏览器,向我询问这个其他页面。”
-
@SelectOr - 感谢您的建议。我在 level1.php 中调用 session_start() (我刚刚更新了我的原始帖子以反映这一点),所以不幸的是,这不是它失败的原因。但是,关于 ALSO 检查级别访问的要点很重要。
标签: php html design-patterns