4

我有这个表格:

<form method="post" action="secret.php">
    <label for="pw">Password: </label><input type="password" name="pw" id="pw" />
</form>

这是secret.php:

<?php 
if(isset($_POST["pw"])) {
    if($_POST["pw"] == "hello") {
        echo("<strong>Good pw.</strong><br />");
    } else {
        echo("<strong>Bad pw.</strong><br />");
        echo("<a href=\"form.php\">Back</a>");
        sleep(5);
    }
} else {
    header("Location: /tut/first/form.php");
}
?>

发生的情况是,如果密码错误,它会在显示 Bad pw 之前休眠。当我提交表单时,它在表单页面上休眠 5 秒,然后更改页面并显示 Bad pw。为什么?

4

3 回答 3

4

发生的事情是您导致 PHP 脚本进入休眠状态。脚本必须在将结果发送回客户端(浏览器)之前完成。*因此,您导致脚本在响应客户端它不是一个好的密码之前需要 5 秒的时间。

由于您不想在这里避免蛮力情况,因此我建议您这样做:

<?php 
if(isset($_POST["pw"])) {
    if($_POST["pw"] == "hello") {
        echo("<strong>Good pw.</strong><br />");
    } else {
        echo("<strong>Bad pw.</strong><br />");
        echo("<script type=\"text/javascript\">");
            echo ("setTimeout(function() {");
                echo ("window.location = form.php;"); //might need a more complete URL here
            echo ("}, 5)"); //sleep for 5 seconds before redirecting
        echo("</script>");
        sleep(5);
    }
} else {
    header("Location: /tut/first/form.php");
}
?>

*输出实际上是在 PHP 脚本中编写的,但是通过缓冲,除了标题和非常大的页面之外,您看不到这有很大的不同。

于 2013-05-31T18:57:31.057 回答
0

您需要研究输出缓冲,尽管从我所见,逻辑是有缺陷的。

可能会有所帮助

于 2013-05-31T18:55:25.570 回答
0

如果您想立即向浏览器回显某些内容,请尝试在flush()要将输出缓冲区刷新到浏览器时执行此操作。此外,您可能需要禁用可能会干扰输出缓冲的压缩(如 gzip)。

但是,话虽如此,您却完全错了。用户所要做的就是打开另一个选项卡/刷新,服务器将再次验证登录信息,所以这样做sleep()不会产生你认为的效果。

我实际上设计了类似的东西,这就是我所做的:

创建一个名为 failed_logins 的数据库表和另一个名为 login_bans 的数据库表,两者都基于 IP 地址。每次用户提供不正确的信息时,在 failed_logins 表中添加一个条目。您要做的是对其进行分层,以便在第一次登录后,用户被禁止 5 秒,在第二次之后,它会上升到 15 秒,并且在一段时间内(比如 2 小时)用户被禁止 3 秒或更多禁赛45秒。这一切都是在服务器端完成的,因此用户无法采取任何措施来规避禁令。因此,您每次访问该页面时都必须检查他们的 IP,以查看他们的 IP 是否已被禁止。

然后在客户端显示一个倒计时计时器,其中包含禁止中剩余的秒数并禁用提交按钮。

于 2013-05-31T19:17:09.027 回答