我对PHP Post/Redirect/Get感到困惑


I am confused about PHP Post/Redirect/Get

在一篇关于防止PHP表单重新提交的文章中,我读到了以下内容:

(不引用)这可能是接收表单数据的页面,例如名为"form.php":

<form action="submit.php">
  <input type="text" name="user" required />
  <input type="password" name="pass" required />
  <input type="submit" value="Log in" />
</form>
因此,处理POST数据的页面将被称为"submit.php"。如果登录正常,下面的代码将运行:
header('Location: /login/form.php?success=true');

但是,用户不能直接导航到上面的URL吗?另外,GET变量的目的是什么?我能否在form。php中编写一个脚本来检查用户是否登录?

在submit.php中,我是否应该将登录的用户名保存为$_SESSION['username'],然后检查isset() At form.php?另外,由于带有"成功"的URL并不漂亮,再次重定向用户是否经济?我应该使用PHP header()还是Javascript window.location.href?如你所见,我有点困惑。

谢谢你的帮助。

但是,用户不能直接导航到上面的URL吗?

是的,他可以。但这不会导致任何不好的事情。

还有,GET变量的目的是什么?

有一些标志,表示表单已成功处理,您需要向用户表示祝贺。

我不能有一个脚本在form.php检查用户是否登录?

嗯,你可以按照你喜欢的方式保存你的代码。没有任何强要求

在submit.php中,我是否应该将登录的用户名保存为$_SESSION['username'],然后检查isset()是否在form.php中?

如果您需要在当前会话中持久化它-是的,这样做。

另外,由于URL中有"成功",它不是真的漂亮,它是经济的重定向用户一次?

重定向。重定向是很便宜的。

我应该使用PHP header()还是Javascript window.location.href?

你绝对应该在php中这样做,否则你会遇到你试图避免遵循prg方式的麻烦。

PRG或Post/Redirect/Get只是一种可以用来防止消息框的模式。具体如何使用取决于你的需要(这篇文章只是一个一般性的建议)。

如果你想在cookie或会话或get变量中标记成功的flash消息,这完全取决于你。第二个重定向没有帮助,顺便说一句,你会知道,如果你玩它。

唯一重要的部分是,在收到POST请求之后,执行重定向。然后,用户仍然可以在历史中来回移动,而不会被要求重新提交POST数据。

模式起作用了,这是一件好事。就在两天前,我又做了一次,一步一步的weppapp安装程序在浏览器界面上导航要好得多。

关于你的重定向

这个代码是错误的:

header('Location:/login/form.php?success=true');

首先,你需要在冒号后面有一个空格:

header('Location: /login/form.php?success=true');

地址必须是一个绝对的URI,它必须包含完整的URL:

header('Location: http://example.com/login/form.php?success=true');

header()的旁边,你应该按照RFC提供一个消息体,许多所谓的"web开发人员"甚至不知道:

$url = 'http://example.com/login/form.php?success=true';
header(sprintf('Location: %s', $url));
printf('<a href="%s">Moved</a>.', $url);
exit;

别忘了出口。当然,这是在重复工作,而不是安装PHP的http扩展,只做这一行:

http_redirect('/login/form.php?success=true');

你可以在这里找到这个漂亮的助手。

总结一下:重要的是你在发布后进行重定向。其他的事情,比如传递一个变量,完全取决于你想怎么做。

是的,您永远不应该依赖GET变量(甚至是隐藏的POST变量)来表示,"当然,让我进入,我是一个有效的用户!"

就我个人而言,我会从链接中剥离GET信息,并完全依赖会话变量。如果您正在使用PHP激活会话,请记住将'session_start();'作为第一行代码。

submit.php

:

<?php
session_start();
if ($_POST['user'] && $_POST['pass']) { // Make sure both variable are set
 if (your_method) {
 // Code to check if the user and pass are valid however you plan
  $_SESSION['user'] = $_POST['user'];
  $_SESSION['loggedin'] = time();
 }
}
header('Location: form.php'); // Either way, pass or fail, return to form.php
exit();
?>

Then in form.php:

<?php
session_start();
$activeuser = false;
if ($_SESSION['user'] && $_SESSION['loggedin'] < (time()+600)) {
// Check if the user exists and the last access was with in 10 minutes.
 $_SESSION['loggedin'] = time(); // If so, keep them up to date!
 $activeuser = true;
}
if ($activeuser) {
 // whatever should show to someone logged in
} else {
 // Show log in form
}
?>

另外,您可能已经知道这一点,但是默认的传输方法是GET,所以一定要在表单标签中指定method="post"。

如果需要,通常最好使用header()来重定向,因为Javascript是客户端,可以避免这会破坏您的网站功能的意图。

POST/REDIRECT/GET背后的主要思想,正如您链接到的文章所指出的那样,是为了避免用户(大多数时候)重新提交数据。一般来说,您不希望相同的POST(使用完全相同的数据)发生两次——实际上,在某些情况下,它最终可能会执行某些操作(例如从信用卡中扣款)第二次,这将是糟糕的。

你在问题中问的大部分都是实现细节(比如在重定向中发送?success请求参数)。

在实践中,通常发生的情况是您的重定向成功。例如,如果用户的输入验证失败,则不重定向,而是重新显示表单和相关的错误消息。

这是一个基本的例子,都在一个脚本中。我尽量只包含重要的内容,尽可能少地包含无关的内容。

login。

<?php
/**
 * ensure user supplied both username & password
 * @return mixed true or an array of error messages
 */ 
function validate_login_values($vars){
    $errors = array();
    if (empty($vars['username'])) $errors[] = 'You must supply a username, genius.';
    if (empty($vars['password'])) $errors[] = 'You must supply a password, dummy.';
    if (empty($errors)) return true;
    return $errors; // $errors must be an array.
}
if (! empty($_POST)){
    $validationResults = validate_login_values($_POST);
    if ($validationResults === true){
        // assume here that authenticate properly escapes it's arguments before sending them
        // to the database.
        if (authenticate($_POST['username'],$_POST['password'])){
            //GREAT SUCCESS!  The user is now logged in.  Redirect to home page
            header("Location: /");
            die();
        }
        $errors[] = 'Invalid username/password.  Try again, slim";
    }else{
        $errors = $validationResults; // validate_login_values created errors.
    }  
}
?>
<h1>Log In, Friend!</h1>]
<?php 
//display errors, if there were any
if (! empty($errors)): ?>
<div class="errors">Something went horribly wrong:
<ul><?php foreach($errors as $e) echo "<li>$e</li>"; ?></ul>
<div>
<?php endif; ?>
<form method="POST">
<!--   //username, password, and submit   -->
</form>