限制失败登录尝试次数

5
我希望限制登录失败的次数。例如,如果一个特定的用户用错误的用户名或密码尝试登录4次,我应该在第4次显示验证码而不是阻止一段特定的时间,并保持显示验证码,除非他提供有效的用户名和密码。一旦用户成功登录,登录尝试将重置为零。
从安全角度来看,检查用户名而不是IP地址的想法是否可行?这种方法可以在不使用数据库的情况下实现吗?因为我认为我不需要存储时间,因为我只会显示recaptcha?请给出您的意见。

1
https://dev59.com/i3RB5IYBdhLWcg3wl4EP https://dev59.com/2kbRa4cB1Zd3GeqP5f2N - Jacob
5个回答

8

如果您不想使用数据库来检查“登录失败次数”,那么只需使用cookie并进行检查。当然,他们可以删除它,但这很麻烦。

然而,我怀疑您已经从数据库中获取了用户名和密码,为什么不在此同时获取最后的登录失败次数呢?

if (isset($_POST['submit_login'])) {

    if (isset($_POST['username']) && isset($_POST['password'])) {
        $username = mysql_real_escape_string($_POST['username']);
        $password = mysql_real_escape_string($_POST['password']);
        // id = unique primary key
        $rs = mysql_query('SELECT id,Username,Password,Failed_logins,IP_address FROM Users WHERE Username = '.$username.'');
        $num = mysql_num_rows($rs);
        if ($num > 0) {
            // I would add a password hash here to $password, and check against the hashed Password from the database
            // But let's check the clean passwords
            $row = mysql_fetch_array($rs);
            if ($password == $row['Password']) {
                // Successful login, set session or whatever you need
                // Reset failed logins
                mysql_query('UPDATE Users SET Failed_logins = 0 WHERE id = '.$row['id'].'');
                header('location: success.php');
            } else {
                // Failed password check
                if ($row['Failed_logins'] > 3) {
                    // Redirect to captcha
                    header('location: captcha.php');
                } else {
                    $ip = $_SERVER['REMOTE_ADDR'];
                    if ($row['IP_address'] != $ip) {
                        // New ip adress, reset failed logins
                        $failed_logins = 0;
                    } else {
                        // Increment failed logins
                        $failed_logins = $row['Failed_logins']+1;
                    }
                    mysql_query('UPDATE Users SET Failed_logins = '.$failed_logins.',IP_address = '.$ip.' WHERE id = '.$row['id'].' ');
                } // End check Failed_logins > 3
            }
        } else {
            // No such Username found in database
            $error = 'no_such_username';
        } // End username check from database

    } else {
        // Either username or password is missing
        $error = 'incomplete_form';
    } // end check for username and password

} // end main submit_login check

类似这样的内容。

编辑:

这是非常老的代码,现在我看到一些问题。但是,至少您应该始终使用PDO(预处理语句)将数据插入数据库中。


2
成功登录后,请记得重置“Failed_logins”。 - jensgram
是的,这很好。因此,failed_login应该仅在成功登录后重置?因此,即使一个人在一年后尝试,它也不会允许?我是否应该添加另一列login_time并比较时间?假设一个人每24小时只能尝试3次,这是个好主意吗? - Roman
如果攻击者不断提供不存在的用户名怎么办? - Roman
我并不是要写完整的代码,只是给你一个框架。当用户成功登录时,当然应该将Failed_logins清零。如果你愿意,可以实现超时功能。你说得对,不应该让一个用户增加另一个用户的Failed_logins。我会存储用户的IP地址,并在IP地址更改时将Failed_logins清零。我会再写一些代码。 - Mattis

1

你要保护什么?

随机用户内容,用户名。

银行信息(我怀疑……)或其他敏感数据,IP地址可能可以,只要使用范围。

你是在问如何做还是应该使用哪个?


1

你确实需要时间,否则如何确定登录尝试是否已过期?如果我在10年的时间跨度内连续失败4次登录,我将被阻止。你想要阻止那些在短时间内尝试多次登录的人。

我建议你使用数据库 - 因为这样你可以同时保留详细的登录历史记录。但像memcached这样的基于内存的解决方案也足够了。

关于要实施哪种安全措施,我建议组合使用

将使用的用户名和IP地址组合起来并存储到你的数据库中。

  1. 使用用户名的登录尝试直接保护你的用户免受攻击。
  2. 使用IP地址信息进行观察和检测,只有在必要时才采取行动。

谢谢你的想法。现在,存储用户的用户名还是IP地址会更有帮助呢?如果攻击者不断提供不存在的用户名和密码会发生什么? - Roman

0

最好的方法是使用数据库。

您需要在数据库中创建一个单独的表,该表将存储三个变量:

(a) IP地址 (尝试登录的用户所在的位置) (b) 登录尝试次数 (c) 日期/时间 (或:当前时间戳)

这种方法唯一的问题就是第一个变量:IP地址

如果用户在网吧里?或者使用公共Wi-Fi? 或者热点?或学校?办公室? 等等

如果您阻止IP地址,则会影响从该位置尝试登录您的网站的所有人。

如果您的网站涉及银行、军事设施或五角大楼之类的事情,则这不是问题。

但是,如果您的网站是一个商业(买卖、游戏或其他),那么阻止特定的地址只会让您的客户恼火!


0
你应该将尝试记录在数据库中并检查用户。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接