我通过限制失败的登录计数来实施强力保护,如下所示:http://madskristensen.net/post/Brute-force-protect-your-website.aspx 但我遇到了两个问题:
来自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();
}
}
}
}
答案 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));
}
}
这样一切正常。