diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/components/AbstractLimiter.java b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AbstractLimiter.java new file mode 100644 index 00000000..4f92f1ca --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AbstractLimiter.java @@ -0,0 +1,65 @@ +package pro.gravit.launchserver.components; + +import pro.gravit.launcher.NeedGarbageCollection; + +import java.util.HashMap; +import java.util.Map; + +public class AbstractLimiter implements NeedGarbageCollection { + public final int maxTrys; + public final int banMillis; + + public AbstractLimiter(int maxTrys, int banMillis) { + this.maxTrys = maxTrys; + this.banMillis = banMillis; + } + + @Override + public void garbageCollection() { + long time = System.currentTimeMillis(); + map.entrySet().removeIf((e) -> e.getValue().time + banMillis < time); + } + + class LimitEntry + { + long time; + int trys; + + public LimitEntry(long time, int trys) { + this.time = time; + this.trys = trys; + } + + public LimitEntry() { + time = System.currentTimeMillis(); + trys = 0; + } + } + protected Map map = new HashMap<>(); + public boolean check(T address) + { + LimitEntry entry = map.get(address); + if(entry == null) + { + map.put(address, new LimitEntry()); + return true; + } + else + { + long time = System.currentTimeMillis(); + if(entry.trys < maxTrys) + { + entry.trys++; + entry.time = time; + return true; + } + if(entry.time + banMillis < time) + { + entry.trys = 1; + entry.time = time; + return true; + } + return false; + } + } +} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java index 844a9e56..11f0d5b5 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java @@ -12,7 +12,8 @@ import pro.gravit.utils.HookException; public class AuthLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable { - private transient final Hook prA = this::preAuthHook; + + private transient AbstractLimiter limiter; private transient LaunchServer srv; @Override public void preInit(LaunchServer launchServer) { @@ -21,7 +22,8 @@ public void preInit(LaunchServer launchServer) { @Override public void init(LaunchServer launchServer) { - launchServer.authHookManager.preHook.registerHook(prA); + limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis); + launchServer.authHookManager.preHook.registerHook(this::preAuthHook); } @Override @@ -30,88 +32,25 @@ public void postInit(LaunchServer launchServer) { } public boolean preAuthHook(AuthResponse.AuthContext context, Client client) { - if (isLimit(context.ip)) { + if (!excludeIps.contains(context.ip) && limiter.check(context.ip)) { throw new HookException(message); } return false; } - static class AuthEntry { - public int value; - - public long ts; - - public AuthEntry(int i, long l) { - value = i; - ts = l; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof AuthEntry)) - return false; - AuthEntry other = (AuthEntry) obj; - if (ts != other.ts) - return false; - return value == other.value; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (int) (ts ^ ts >>> 32); - result = prime * result + value; - return result; - } - - @Override - public String toString() { - return String.format("AuthEntry {value=%s, ts=%s}", value, ts); - } - } - - - public static final long TIMEOUT = 10 * 60 * 1000; //10 минут public int rateLimit; public int rateLimitMilis; public String message; - - public transient HashMap map = new HashMap<>(); public List excludeIps = new ArrayList<>(); @Override public void garbageCollection() { - long time = System.currentTimeMillis(); - long max_timeout = Math.max(rateLimitMilis, TIMEOUT); - map.entrySet().removeIf(e -> e.getValue().ts + max_timeout < time); - } - - public boolean isLimit(String ip) { - if (excludeIps.contains(ip)) return false; - if (map.containsKey(ip)) { - AuthEntry rate = map.get(ip); - long currenttime = System.currentTimeMillis(); - if (rate.ts + rateLimitMilis < currenttime) rate.value = 0; - if (rate.value >= rateLimit && rateLimit > 0) { - rate.value++; - rate.ts = currenttime; - return true; - } - rate.value++; - rate.ts = currenttime; - return false; - } - map.put(ip, new AuthEntry(1, System.currentTimeMillis())); - return false; + if(limiter != null) + limiter.garbageCollection(); } @Override public void close() throws Exception { - srv.authHookManager.preHook.unregisterHook(prA); + srv.authHookManager.preHook.unregisterHook(this::preAuthHook); } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java b/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java index 2cef6770..f5293874 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java @@ -12,18 +12,17 @@ public class RegLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable { - public static final long TIMEOUT = 12 * 60 * 60 * 1000; //12 часов + private transient AbstractLimiter limiter; public transient LaunchServer launchServer; public int rateLimit; public int rateLimitMilis; public String message; - public transient HookSet.Hook hook; - public transient HashMap map = new HashMap<>(); public List excludeIps = new ArrayList<>(); @Override public void preInit(LaunchServer launchServer) { + limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis); this.launchServer = launchServer; } @@ -34,43 +33,24 @@ public void init(LaunchServer launchServer) { @Override public void postInit(LaunchServer launchServer) { - launchServer.authHookManager.registraion.registerHook(context -> { - if (isLimit(context.ip)) { - throw new HookException(message); - } - return false; - }); + launchServer.authHookManager.registraion.registerHook(this::registerHook); } - @Override - public void garbageCollection() { - long time = System.currentTimeMillis(); - long max_timeout = Math.max(rateLimitMilis, TIMEOUT); - map.entrySet().removeIf(e -> e.getValue().ts + max_timeout < time); - } - - public boolean isLimit(String ip) { - if (excludeIps.contains(ip)) return false; - if (map.containsKey(ip)) { - AuthLimiterComponent.AuthEntry rate = map.get(ip); - long currenttime = System.currentTimeMillis(); - if (rate.ts + rateLimitMilis < currenttime) rate.value = 0; - if (rate.value >= rateLimit && rateLimit > 0) { - rate.value++; - rate.ts = currenttime; - return true; - } - rate.value++; - rate.ts = currenttime; - return false; + public boolean registerHook(AuthHookManager.RegContext context) + { + if (limiter.check(context.ip)) { + throw new HookException(message); } - map.put(ip, new AuthLimiterComponent.AuthEntry(1, System.currentTimeMillis())); return false; } + @Override + public void garbageCollection() { + if(limiter != null) + limiter.garbageCollection(); + } @Override public void close() throws Exception { - if(hook != null) - launchServer.authHookManager.registraion.unregisterHook(hook); + launchServer.authHookManager.registraion.unregisterHook(this::registerHook); } }