mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +03:00
[FEATURE] AbstractLimiter, переделка AuthLimiter и RegLimiter
This commit is contained in:
parent
ca19734a88
commit
45b6f64cd7
3 changed files with 86 additions and 102 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,8 @@
|
|||
import pro.gravit.utils.HookException;
|
||||
|
||||
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;
|
||||
@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<String, AuthEntry> map = new HashMap<>();
|
||||
public List<String> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String> limiter;
|
||||
public transient LaunchServer launchServer;
|
||||
public int rateLimit;
|
||||
public int rateLimitMilis;
|
||||
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<>();
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue