我有一个网站,我想阻止来自BOTs
的请求,并尝试强行登录我的网站。
现在我使用Session
存储登录尝试并在3次登录失败后显示验证码但是如果用户关闭浏览器则会出现问题。
我应该考虑采取哪种解决方案来阻止BOTs
和暴力登录?我应该存储用户系统或浏览器的哪些属性来管理他/她的下次登录?
编辑1)
我不使用ASP.NET成员资格提供程序。我使用自己的身份验证和授权类
答案 0 :(得分:32)
您无法使用会话,因为它要求客户端为您存储Cookie,并且攻击者不会帮助您。你需要一些全球状态。
您无需费心追踪IP地址,因为坏人只会使用Anonymyzing Proxy。
不要使用帐户锁定,除非您必须(PCI要求),因为这只是让攻击者DoS您的用户。
您还希望通过让服务器做太多工作来避免自己的行为。
这有效:
验证失败后,将用户名存储在全局状态,并带有计数。如果使用该用户名进行更多不成功的身份验证,则会同步count++
。我为此使用redis。
如果count >= threshold
,则需要在继续之前解决CAPTCHA值。在登录屏幕上显示CAPTCHA。
在成功身份验证后,清除存储的全局状态的用户名。为用户提供“受信任的用户代理”HMAC'd cookie,因此他们将来不必使用该用户名的CAPTCHA。
您可以对密码执行相同操作,但可能具有更高的阈值。
如果您不喜欢CAPTCHA ,则需要工作证明,例如让客户计算并提交非常大数的素因子。
当您使用它时,请确保使用bcrypt来对您的密码进行哈希处理,并且成本因素足够高,以便使用> = 250ms来密码密码。这会降低服务器速度,但也会降低攻击者的速度。除非他们通过CAPTCHA(如果需要),否则请避免散列。
鼓励用户使用漫长,复杂,令人难忘的?密码,这样他们就更难以暴力破解。
答案 1 :(得分:4)
最简单的方法是使用cloudflare(https://www.cloudflare.com/features-security)等CDN提供商来解决您的问题。很多CDN都提供这个,而cloudflare有免费关税。
或者,如果您是自己尝试这样做,那么您可以计算数据库中每个用户名的尝试次数,并根据此计数显示验证码。
答案 2 :(得分:3)
根据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<InvalidLogin> user = null;
if (HttpContext.Current.Application["Users"] == null) //Adding List to Application State
{
user = new List<InvalidLogin>();
}
else
{
user = (List<InvalidLogin>)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
}
}
}
}
答案 3 :(得分:1)
如果您使用自己的身份验证和授权类,则需要计算每个用户登录失败的次数及其日期和时间。
如果达到了尝试次数,您将打破下次登录过程的限制,并显示错误消息,例如“您的帐户已被屏蔽15分钟,请稍后再试”。
例如。 登录表名为[登录]。
You need to add new colums:
1. [LastLoginAttemptAt] DATETIME NULL
2. [LoginFailedAttemptsCount] INT NOT NULL DEFAULT 0
因此,您的班级登录将包含以下新字段:
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版本):
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!
}
}
答案 4 :(得分:0)
您可以在几次尝试失败后暂停帐户,并让用户回答安全问题以重新启用它。也不要重复使用最后几个密码,你应该是安全的。
现在,如果你想通过编码来表达,那么请保存第三次登录尝试时间[MaxAttemptTime]
(DateTime.Now
)以及释放帐户[ReleaseTime]
的时间(比如20分钟后) DateTime.Now.AddMinutes(20)
)。
现在,每当同一用户尝试登录时,都应根据[ReleaseTime]
拒绝。在成功登录真实用户时重置这些计数器。
答案 5 :(得分:0)
我唯一想补充的是,其他人无法在可能的情况下提醒机器人他们已经检测到这一事实。如果你用一些信息阻止他们,那么他们只会记下他们要检测和调整的内容。如果你注意到了#34;以ip为例,只是不允许他们输入的密码成功。他们会被愚弄,以为你有一些复杂的密码等,然后去其他地方,而不知道你是否注意到它们。
我还建议存储&#34;尝试&#34;在带有ip的数据库中。然后,您可以轻松返回并查看针对您网站的尝试。你可以查询网络日志,但这更痛苦。我还记录了成功的登录信息,因此我可以注意到机器人何时进入并进行进一步的研究。
答案 6 :(得分:0)
如果我这样做,我会使用数据库中的列来存储登录尝试次数和第一次尝试的日期时间戳。然后在登录
周围有一些逻辑 if(loginAttempt>5 && DateTime.Now<loginDate.AddMinute(5))
{
//Locked out
}