【问题标题】:Trying to understand the Post/Redirect/Get design pattern (implemented with PHP)试图理解 Post/Redirect/Get 设计模式(用 PHP 实现)
【发布时间】: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


【解决方案1】:

Post Redirect Get 的作用是阻止用户在提交表单后刷新他们被重定向到的页面时重新发送他们的 POST 数据。当你想实现一个 PRG 时,你应该像这样将 HTTP 标头代码设置为 303:

header('Location: level1.php', 303);

【讨论】:

【解决方案2】:

如果凭据有效,则 login.php 创建会话以建立用户的身份验证状态:

我也在黑暗中拍摄,但我的印象是您可能会在 login.php 中设置会话之前输出一些内容。将session_start 作为每个文件中的第一条指令。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    • 2019-05-21
    • 1970-01-01
    • 1970-01-01
    • 2015-04-30
    相关资源
    最近更新 更多