在一段时间内阻止多次不成功登录的请求

我有一个网站,我想阻止BOTs请求,并尝试暴力登录我的网站。

现在,我正在使用Session存储登录尝试并在3次登录失败后显示validation码,但是如果用户关闭浏览器,则会出现问题。

我应该考虑采取什么样的解决方案来防止BOTs和暴力登录? 我应该存储用户系统或浏览器的哪些属性来管理他/她的下一次登录?

编辑1)

我不使用ASP.NET成员资格提供程序。 我正在使用自己的身份validation和授权类

您不能使用会话,因为它要求客户端为您存储cookie,并且攻击者不会帮助您。 你需要一些全球状态。

您无需费心追踪IP地址,因为坏人只会使用Anonymyzing Proxy。

除非必须(PCI要求),否则不要使用帐户锁定,因为这只是让攻击者DoS您的用户。

您还希望通过使服务器执行太多工作来避免自己操作。

这有效:

validation失败后,将用户名存储在全局状态,以及计数。 如果使用该用户名进行更多不成功的身份validation,则同步count++ 。 我为此使用redis。

如果count >= threshold ,则需要在继续之前解决CAPTCHA值。 在登录屏幕上显示CAPTCHA。

validation成功后 ,清除存储的全局状态用户名。 为用户提供“可信用户代理”HMAC的cookie ,因此他们将来不需要在该UA上使用该用户名的CAPTCHA。

您可以对密码执行相同操作 ,但可能具有更高的阈值。

如果您不喜欢CAPTCHA,那么请求工作certificate,例如让客户计算并提交非常大数量的素因子。

当你在它的时候,确保你使用bcrypt来哈希你的密码,并且成本因子足够高,需要> = 250ms来散列密码。 这会降低服务器速度,但也会降低攻击者的速度。 避免散列,除非它们通过CAPTCHA(如果需要)。

鼓励用户使用冗长,复杂,令人难忘的? 密码,这样他们就更难以蛮力了。

最简单的方法是使用cloudflare( https://www.cloudflare.com/features-security )等CDN提供商为您提供解决方案。 很多CDN都提供此function,而cloudflare则提供免费资费。

或者,如果您自己尝试执行此操作,则可以计算数据库中每个用户名的尝试次数,并根据此计数显示validation码。

识别基于IpAddress(匿名代理)的无效登录。每个无效的登录ip和登录计数和时间将存储在应用程序状态中。

创建类InvalidLogin

 public class InvalidLogin { public string IP { get; set; } public DateTime Attempttime { get; set; } public int AttemptCount { get; set; } } 

登录活动

 protected void Login_Click(object sender, EventArgs e) { bool Testsuccessfullogin = false; if (Testsuccessfullogin) { //Your code after successfull login } else { //Invalid Login --- Capture Each login event based on IP string strIp; strIp = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; //when user is behind proxy server if (strIp == null) { strIp = Request.ServerVariables["REMOTE_ADDR"];//Without proxy } List user = null; if (HttpContext.Current.Application["Users"] == null) //Adding List to Application State { user = new List(); } else { user = (List)HttpContext.Current.Application["Users"]; } var remove = user.RemoveAll(x => x.Attempttime < DateTime.Now.AddMinutes(-15));//Remove IP Before 15 minutes(Give 15 Min Time Next Login) var checkLogged = user.Find(x => x.IP == strIp); if (checkLogged == null) { user.Add(new InvalidLogin { IP = strIp, Attempttime = DateTime.Now, AttemptCount = 1 }); Application.Lock(); HttpContext.Current.Application["Users"] = user; Application.UnLock(); } else { if (checkLogged.AttemptCount < 4) { checkLogged.Attempttime = DateTime.Now; checkLogged.AttemptCount++; Application.Lock(); HttpContext.Current.Application["Users"] = user; Application.UnLock(); } } if (checkLogged != null) { if (checkLogged.AttemptCount > 3) { captcha.Visible = true; //Showing captcha } } } } 

如果您使用自己的身份validation和授权类,则需要计算每个用户登录失败的次数及其日期和时间。

如果达到了尝试次数,您将打破下一次登录过程的限制,并显示错误消息,例如“您的帐户已被阻止15分钟,请稍后再试”。

例如。 登录表名为[登录]。

 You need to add new colums: 1. [LastLoginAttemptAt] DATETIME NULL 2. [LoginFailedAttemptsCount] INT NOT NULL DEFAULT 0 

因此,您的类Login将包含以下新字段:

 public class Login { public DateTime? LastLoginAttemptAt {get;set;} public int LoginFailedAttemptsCount {get;set;} } 

此外,您还需要存储一些配置变量 – 登录失败尝试的最大次数值和阻止期限。

 const int MaxNumberOfFailedAttemptsToLogin = 10; const int BlockMinutesAfterLimitFailedAttemptsToLogin = 15; // 15 min 

在signIn方法中,您将执行以下操作(代码的原始示例,而不是prod-version):

 public void SignIn(string username, string password) { var login = _userService.TryGetLogin(username); if (login == null){ // Login by username not found. // Return error message "Invalid username or password" return; } if (login.LoginFailedAttemptsCount > MaxNumberOfFailedAttemptsToLogin && login.LastLoginAttemptAt.HasValue && DateTime.Now < login.LastLoginAttemptAt.Value.AddMinutes(BlockMinutesAfterLimitFailedAttemptsToLogin)) { // Login is blocked, need to break the process. // Return error message "Your account was blocked // for a 15 minutes, please try again later." return; } else { login.LoginFailedAttemptsCount = 0; login.LastLoginAttemptAt = DateTime.Now; } var success = login.ValidatePassword(password); if (!success) { // Invalid password, need to update the number of attempts. login.LastLoginAttemptAt = DateTime.Now; //or UTC login.LoginFailedAttemptsCount++; // Update(login); // Return error message "Invalid username or password" return; } else { login.LoginFailedAttemptsCount = 0; login.LastLoginAttemptAt = DateTime.Now; // Update(login); // Success! } } 

您可以在几次尝试失败后暂停帐户,并让用户回答安全问题以重新启用它。 另外,不允许重复使用最后几个密码,您应该是安全的。

现在,如果你想通过编码这样做,那么保存第三次登录尝试时间[MaxAttemptTime]DateTime.Now )和释放帐户[ReleaseTime] [MaxAttemptTime]时间(比如20分钟后DateTime.Now.AddMinutes(20) ) 。

现在,每次同一用户尝试登录时,都应根据[ReleaseTime]拒绝。 在成功登录时为重要用户重置这些计数器。

我想补充一点,其他人没有的是,在可能的情况下,你不想提醒机器人他们已被发现的事实。 如果你用一些信息阻止他们,那么他们只会记下他们要检测和调整的内容。 例如,如果你通过ip“注意到”它们,就不要让他们输入的密码成功。 他们会被愚弄,以为你有一些复杂的密码等,然后去其他地方,而不知道你是否注意到它们。

我还建议使用ip将“尝试”存储在数据库中。 然后,您可以轻松返回并查看针对您网站的尝试。 你可以查询网络日志,但这更痛苦。 我还记录了成功的登录信息,因此我可以注意到机器人何时进入并进行进一步的研究。

如果我这样做,我将使用数据库中的列来存储登录尝试次数和第一次尝试的日期时间戳。 然后在登录时有一些逻辑

  if(loginAttempt>5 && DateTime.Now