Block request for multiple unsuccessful logins for

2019-01-07 15:21发布

I have a web site and I want to block request from BOTs and attempt brute force login to my web site.

Now I'm using Session for storing login attempt and show captcha after 3 unsuccessful login but there is a problem.Session will be removed, if user closes the browser.

What kind of solution I should consider to prevent BOTs and brute force login? What property of user system or browser I should store to manage his/her next login?

Edit 1)

I don't use ASP.NET Membership provider. I'm using my own authentication and authorization classes

7条回答
冷血范
2楼-- · 2019-01-07 15:41

Identify invalid login based on IpAddress(anonymous proxy).That Each invalid login ip and login count&time that will stored in Application State.

Create Class InvalidLogin

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

Login Event

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楼-- · 2019-01-07 15:48

The easiest would be to front your solution with a CDN provider such as cloudflare (https://www.cloudflare.com/features-security) that will detect bots for you. Lots of the CDNs offer this, and cloudflare have a free tariff.

Alternatively if you are attempting to do this yourself, then you can count the number of attempts per username in your database and present a captcha based on this count.

查看更多
做自己的国王
4楼-- · 2019-01-07 15:48

only thing that I'd like to add that others haven't is that where possible, you don't want to alert bots to the fact that they've been detected. if you block them with some message, then they will just make note of what they did to be detected and adjust. if you're "noticing" them by ip for example, just don't allow the password that they're entering to ever succeed. they will be fooled into thinking that you have some complicated passwords etc, and go elsewhere, without ever knowing for sure that you noticed them.

I would also suggest storing the "attempts" in a database with ip. you can then easily go back and review attempts that have been made against your site. you could query the web logs, but that's more painful. I also log successful logins so I can notice when bots do get in to go back and apply further research.

查看更多
不美不萌又怎样
5楼-- · 2019-01-07 15:49

If i were doing this i would use a column in a database to store the login attempt number and a date time stamp for the first attempt. Then have some logic around the login

 if(loginAttempt>5 && DateTime.Now<loginDate.AddMinute(5))
{
    //Locked out
}
查看更多
倾城 Initia
6楼-- · 2019-01-07 15:53

If you are using your own authentication and authorization classes, you need to count the number of failed attempt to login for each user and it's date and time.

If the number of attempts is reached the limit that you will break the next login process with error message like "Your account was blocked for a 15 minutes, please try again later."

For example. Table of logins is named [Logins].

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

So, your class Login will have these new fields:

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

Also you need to store somewere configuration variable - the value of max number of failed attempts to login and block period.

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

On a signIn method you will do the following (primitive example of code, not a 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!
    }
}
查看更多
爷、活的狠高调
7楼-- · 2019-01-07 16:00

You can suspend the account after few failed attempts and have user answer security questions to re-enable it. Also do not allow the reuse of a last few passwords and you should be safe.

Now that being said if you want to do it via coding then save the third login attempt time [MaxAttemptTime] (DateTime.Now) and time to release the account [ReleaseTime] (say after 20 minutes DateTime.Now.AddMinutes(20)).

Now every time there is an attempt from the same user to login it should be declined based on the [ReleaseTime]. Reset these counters on the successful login for a genuine user.

查看更多
登录 后发表回答