0

我通过限制登录失败次数实现了蛮力保护,如下所示:http: //madskristensen.net/post/Brute-force-protect-your-website.aspx 但我遇到了两个问题:

  • 经过一定时间(在我的情况下为 2 分钟)缓存中的记录没有过期,我无法再次登录。这意味着当函数检查失败尝试的次数时,它仍然会在这 5 分钟后获得允许的最大值
  • 据我了解,来自 MSDN 的缓存是应用程序的单一存储。从我在我的应用程序中看到的情况来看,缓存似乎是每个应用程序每个 IP 的。为什么?有什么建议么?这是我的代码:

    int CountOfFailedLoginAttempts()
    {
       if(Cache["L1|"+TextBox1.Text]==null)
       {
           return 0;
       }
       return (int) Cache["L1|" + TextBox1.Text];
    
    }
    void AddFailedAttempt()
    {
        if(Cache["L1|"+TextBox1.Text]==null)
        {
            Cache.Insert("L1|"+TextBox1.Text,1,null,System.Web.Caching.Cache.NoAbsoluteExpiration,new TimeSpan(0,2,0));
        }
        else
        {
            int tries = (int) Cache["L1|" + TextBox1.Text];
            Cache["L1|" + TextBox1.Text] = tries + 1;
        }
    }
    void ClearFailedAttemptCounter()
    {
        Cache.Remove("L1|" + TextBox1.Text);
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        if (CountOfFailedLoginAttempts() >= 5)
        {
            Label1.Text = "Login will be unavailable for 2 minutes";
        }
        else
        {
            SqlConnection con =
                new SqlConnection("valid connection string");
            SqlCommand cmd = new SqlCommand("Select top 1 password from users WHERE UserName=@UN", con);
            cmd.CommandTimeout = 600;
            cmd.Parameters.Add(new SqlParameter("UN", TextBox1.Text));
            con.Open();
            string res = (string) cmd.ExecuteScalar();
            con.Close();
            if (res == TextBox2.Text)
            {
                FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, true);
                ClearFailedAttemptCounter();
            }
            else
            {
                Label1.Text = "Wrong password. "+(5-CountOfFailedLoginAttempts()).ToString()+"more attempts and access will be suspended for 2 minutes.";
                AddFailedAttempt();
            }
        }
    }
    

    }

4

2 回答 2

2

您正在使用滑动到期(2 分钟),这意味着您的缓存项将保留,而有人仍在该时间内读取该值。这意味着如果您每分钟都重试,您的帐户将被永远封锁。

缓存是缓存,不是关键数据存储。您不能指望剩余两分钟的项目,服务器上的内存压力可能会迫使 ASP.NET 从缓存中逐出项目。网络农场/花园也有可能为您提供多个工作进程(可能分布在几台机器上),它们都将拥有自己的缓存。

于 2012-10-07T12:12:21.483 回答
0

感谢您的回答。事实证明,问题出在这一行:

Cache["L1|" + TextBox1.Text] = tries + 1;

机制与我想象的完全不同。它不是替换值,而是删除缓存中指定键的值,并插入新的值,没有过期设置。正因为如此,价值似乎永不过期。这与绝对和滑动到期模式有关。我已经解决了这样的问题:

void AddFailedAttempt()
    {
        if(Cache["L1|"+TextBox1.Text]==null)
        {
            Cache.Insert("L1|"+TextBox1.Text,1,null,System.Web.Caching.Cache.NoAbsoluteExpiration,TimeSpan.FromMinutes(2));
        }
        else
        {
            int tries = (int) Cache["L1|" + TextBox1.Text];
            Cache.Remove("L1" + TextBox1.Text);
            Cache.Insert("L1|" + TextBox1.Text, tries+1, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(2));
        }
    }

这样,一切正常。

于 2012-10-07T13:11:33.987 回答