[FEATURE] AbstractLimiter, переделка AuthLimiter и RegLimiter

This commit is contained in:
Gravit 2019-08-09 23:28:08 +07:00
parent ca19734a88
commit 45b6f64cd7
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
3 changed files with 86 additions and 102 deletions

View file

@ -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<T> 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<T, LimitEntry> 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;
}
}
}

View file

@ -12,7 +12,8 @@
import pro.gravit.utils.HookException; import pro.gravit.utils.HookException;
public class AuthLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable { public class AuthLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable {
private transient final Hook<AuthResponse.AuthContext, Client> prA = this::preAuthHook;
private transient AbstractLimiter<String> limiter;
private transient LaunchServer srv; private transient LaunchServer srv;
@Override @Override
public void preInit(LaunchServer launchServer) { public void preInit(LaunchServer launchServer) {
@ -21,7 +22,8 @@ public void preInit(LaunchServer launchServer) {
@Override @Override
public void init(LaunchServer launchServer) { public void init(LaunchServer launchServer) {
launchServer.authHookManager.preHook.registerHook(prA); limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis);
launchServer.authHookManager.preHook.registerHook(this::preAuthHook);
} }
@Override @Override
@ -30,88 +32,25 @@ public void postInit(LaunchServer launchServer) {
} }
public boolean preAuthHook(AuthResponse.AuthContext context, Client client) { 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); throw new HookException(message);
} }
return false; 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 rateLimit;
public int rateLimitMilis; public int rateLimitMilis;
public String message; public String message;
public transient HashMap<String, AuthEntry> map = new HashMap<>();
public List<String> excludeIps = new ArrayList<>(); public List<String> excludeIps = new ArrayList<>();
@Override @Override
public void garbageCollection() { public void garbageCollection() {
long time = System.currentTimeMillis(); if(limiter != null)
long max_timeout = Math.max(rateLimitMilis, TIMEOUT); limiter.garbageCollection();
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;
} }
@Override @Override
public void close() throws Exception { public void close() throws Exception {
srv.authHookManager.preHook.unregisterHook(prA); srv.authHookManager.preHook.unregisterHook(this::preAuthHook);
} }
} }

View file

@ -12,18 +12,17 @@
public class RegLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable { public class RegLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable {
public static final long TIMEOUT = 12 * 60 * 60 * 1000; //12 часов private transient AbstractLimiter<String> limiter;
public transient LaunchServer launchServer; public transient LaunchServer launchServer;
public int rateLimit; public int rateLimit;
public int rateLimitMilis; public int rateLimitMilis;
public String message; public String message;
public transient HookSet.Hook<AuthHookManager.RegContext> hook;
public transient HashMap<String, AuthLimiterComponent.AuthEntry> map = new HashMap<>();
public List<String> excludeIps = new ArrayList<>(); public List<String> excludeIps = new ArrayList<>();
@Override @Override
public void preInit(LaunchServer launchServer) { public void preInit(LaunchServer launchServer) {
limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis);
this.launchServer = launchServer; this.launchServer = launchServer;
} }
@ -34,43 +33,24 @@ public void init(LaunchServer launchServer) {
@Override @Override
public void postInit(LaunchServer launchServer) { public void postInit(LaunchServer launchServer) {
launchServer.authHookManager.registraion.registerHook(context -> { launchServer.authHookManager.registraion.registerHook(this::registerHook);
if (isLimit(context.ip)) {
throw new HookException(message);
}
return false;
});
} }
@Override public boolean registerHook(AuthHookManager.RegContext context)
public void garbageCollection() { {
long time = System.currentTimeMillis(); if (limiter.check(context.ip)) {
long max_timeout = Math.max(rateLimitMilis, TIMEOUT); throw new HookException(message);
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;
} }
map.put(ip, new AuthLimiterComponent.AuthEntry(1, System.currentTimeMillis()));
return false; return false;
} }
@Override
public void garbageCollection() {
if(limiter != null)
limiter.garbageCollection();
}
@Override @Override
public void close() throws Exception { public void close() throws Exception {
if(hook != null) launchServer.authHookManager.registraion.unregisterHook(this::registerHook);
launchServer.authHookManager.registraion.unregisterHook(hook);
} }
} }