feat(web): implement progressive IP lockout duration scaling based on block counts
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 22s
Prepare Release / Build & Create Release (push) Successful in 59s
Prepare Release / Release Notification (push) Successful in 1s
Validators (Pushes and Pull Requests) / validate-core (push) Successful in 2m1s
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 22s
Prepare Release / Build & Create Release (push) Successful in 59s
Prepare Release / Release Notification (push) Successful in 1s
Validators (Pushes and Pull Requests) / validate-core (push) Successful in 2m1s
This commit is contained in:
@@ -9,9 +9,10 @@ public interface IIpLockoutService
|
|||||||
|
|
||||||
public class IpLockoutService : IIpLockoutService
|
public class IpLockoutService : IIpLockoutService
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, (int Attempts, DateTime LockedUntil)> _attemptLog = [];
|
private readonly Dictionary<string, (int Attempts, int LockoutCount, DateTime LockedUntil)> _attemptLog = [];
|
||||||
private const int MaxFailedAttempts = 3;
|
private const int MaxFailedAttempts = 3;
|
||||||
private const int LockoutDurationMinutes = 15;
|
private const int LockoutDurationMinutes = 15;
|
||||||
|
private const int MaxLockoutDurationMinutes = 1440; // 24 hours cap
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
|
|
||||||
public bool IsLockedOut(string ipAddress)
|
public bool IsLockedOut(string ipAddress)
|
||||||
@@ -23,7 +24,11 @@ public class IpLockoutService : IIpLockoutService
|
|||||||
if (DateTime.UtcNow < record.LockedUntil)
|
if (DateTime.UtcNow < record.LockedUntil)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
_attemptLog.Remove(ipAddress);
|
// Reset failed attempts but keep the LockoutCount to calculate progressive delay on next failure
|
||||||
|
if (record.Attempts >= MaxFailedAttempts)
|
||||||
|
{
|
||||||
|
_attemptLog[ipAddress] = (0, record.LockoutCount, DateTime.MinValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -39,14 +44,19 @@ public class IpLockoutService : IIpLockoutService
|
|||||||
record.Attempts++;
|
record.Attempts++;
|
||||||
if (record.Attempts >= MaxFailedAttempts)
|
if (record.Attempts >= MaxFailedAttempts)
|
||||||
{
|
{
|
||||||
record.LockedUntil = DateTime.UtcNow.AddMinutes(LockoutDurationMinutes);
|
// Calculate exponential progressive lockout duration: 15 * 2^LockoutCount
|
||||||
|
var durationMinutes = LockoutDurationMinutes * Math.Pow(2, record.LockoutCount);
|
||||||
|
durationMinutes = Math.Min(durationMinutes, MaxLockoutDurationMinutes);
|
||||||
|
|
||||||
|
record.LockedUntil = DateTime.UtcNow.AddMinutes(durationMinutes);
|
||||||
|
record.LockoutCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
_attemptLog[ipAddress] = record;
|
_attemptLog[ipAddress] = record;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_attemptLog[ipAddress] = (1, DateTime.UtcNow);
|
_attemptLog[ipAddress] = (1, 0, DateTime.MinValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user