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;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue