How to solve this Timeslot problem in C #

I am trying to solve this problem:

  • The user receives 10 login attempts every 5 minutes.
  • If the user exceeds 10 attempts, I show "you need to wait for the login"
  • Once 5 minutes have passed, I need to reset the number of attempts and ask the user to execute another 10 times.

I would like to do this without using Timer , and I save most of this information in Session

 public class LoginExp { public DateTime FirstAttempt; public int NumOfAttempts; } 

I keep FirstAttempt DateTime on page load.

In the "Login" window, click:

  • I increase NumOfAttempts
  • I need to check if NumOfAttempts <10 will be inside the same 5 minute time interval. I could get the number of minutes elapsed between FirstAttempt and DateTime.Now and make a mod of 5, but that won’t tell me what time interval it is (In other words, the user can try 3 times from the 2nd minute and then returns in the 7th minute to try mod will give me the same value.

Any thoughts on how I can do this?

+6
source share
5 answers

You can save a list of timestamps and use this to determine if the user is blocked. This is not complete code, but here is the main idea:

 // Store a list of attempts var attempts = new List<DateTime>(); // Determine if 10 or more attempts have been made in the last 5 minutes bool lockout = attempts.Where(a => (DateTime.Now - a).TotalMinutes <= 5).Count() >= 10; // Register an attempt attempts.Add(DateTime.Now); // Remove attempts older than 5 minutes attempts.Where(a => (DateTime.Now - a).TotalMinutes > 5).ToList() .ForEach(a => attempts.Remove(a)); 

You can also save attempts to a database that will provide you with a folder for security. The same methodology will apply - read records for less than 5 minutes.

+2
source

Do not use a timer, please. Provide space for this data along with user data so that it is stored where some form of their credentials is stored. Just keep the last login attempts and the number of attempts - if the time is greater than n, then the next attempt clears the previous counter and starts at 0, etc.

+6
source

The answer depends on how you interpret this requirement. Namely, is this a 5-minute time interval on a sliding scale?

For hard application of the requirement, you will need to create a database table for login attempts, with each entry including a key to the user entry and the time stamp of the login attempt. Then, for each attempt, run a query like

 delete from login_attempts where user=[user] and attempt_time<[now - 5 minutes] select count(*) from login_attempts where user=[user] 

(where the values ​​in square brackets are replaced by the appropriate values, regardless of whether you use a prepared statement or something else)

Then, if the returned number is> 10, you block the attempt.

(I suggest deleting old attempts every time to keep the table clean. Alternative methods are possible.)

If this requirement does not require a strict requirement, and you do not want to create a new table, you can simplify it, for example, by adding recent attempts and counting the user record. Then on every attempt (pseudo code here ...):

 read last_attempt and attempt_count if last_attempt < now - 5 minutes then attempt_count=0 endif if attempt_count>10 then display error else if attempt_fails then last_attempt=now attempt_count=attempt_count+1 endif 

This will not strictly meet the stated requirements: if the user tried once every 4 minutes, then after 40 minutes we would say that he had 10 bad attempts, when in fact all but one were more than 5 minutes ago, But it would be it’s easier to create a new table and achieve what I assume is the goal of not letting someone crack the password with brute force.

+1
source

To implement a 5-minute rolling window, you need to know the time of each attempt, and not just the first or last.

Store every login attempt in the database. As noted in the comments, just using the session cache is easy to get around.

 username | time mr.mindor | 00:00:00 mr.mindor | 00:01:00 

etc .. then for each login attempt, check that there are 10 or fewer attempts ...

 Select count(*) from LOGIN_ATTEMPTS where username = @current_user AND time > DATEADD(m,-5,GetDate()) 

You can temporarily hold LOGIN_ATTEMPTS for security / audit purposes or periodically clear it or with a successful login.

Problems saving only the first or last time and quantity.
Without each time, you cannot determine the distribution of attempts.

Solution for the first attempt:

Only with the first time and quantity attempt can you prevent more than 10 attempts in the 5 minutes following first, but not prevent more than 10 attempts in any given 5-minute interval.
Example: you can have 1 at 0:00 and 9 at 4:59, and another 10 seconds at 5:01 for 19 seconds.

 attempt_time | record 0:00 | {0:00, 1} 4:59 | {0:00, 2} 4:59 | {0:00, 3} 4:59 | {0:00, 4} 4:59 | {0:00, 5} 4:59 | {0:00, 6} 4:59 | {0:00, 7} 4:59 | {0:00, 8} 4:59 | {0:00, 9} 4:59 | {0:00, 10} 5:01 | {5:00, 1} // 10 since 4:59 5:02 | {5:00, 2} // 11 since 4:59 

Solution based on last attempt:
By saving only the time of the last attempt and the counter, you can prevent more than 10 attempts in any 5-minute interval, but in fact it is much more restrictive. This will prevent more than 10 attempts that appear within 5 minutes of the previous attempt.
Example. If there are attempts every 4 minutes, your counter will never reset.

 attempt_time | record 0:00 | {0:00, 1} 4:00 | {4:00, 2} // 2 in last 5 minutes 8:00 | {8:00, 3} // 2 in last 5 minutes ... 40:00 | {40:00,11} // blocked but only 2 in last 5 minutes. 
0
source

The timer is ugly here. Just keep the Attempts table. Save UserId, attempt time and success / failure flag.

From there, logic is self-evident.

0
source

All Articles