缓存中的存储问题

时间:2012-10-07 11:53:08

标签: asp.net caching

我通过限制失败的登录计数来实施强力保护,如下所示: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();
            }
        }
    }
    

    }

2 个答案:

答案 0 :(得分:2)

您正在使用滑动过期(2分钟),这意味着当某人仍然在该时间内读取值时,您的缓存项目将保留。这意味着如果您每分钟都在重试,您的帐户将永久被阻止。

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

答案 1 :(得分:0)

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

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

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

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));
        }
    }

这样一切正常。