[FEATURE] RegLimiterComponent

This commit is contained in:
Gravit 2019-07-01 16:07:33 +07:00
parent 2d887c86a9
commit 07dd7bcfc8
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
5 changed files with 108 additions and 1 deletions

View file

@ -62,6 +62,7 @@
import pro.gravit.launchserver.binary.ProguardConf; import pro.gravit.launchserver.binary.ProguardConf;
import pro.gravit.launchserver.components.AuthLimiterComponent; import pro.gravit.launchserver.components.AuthLimiterComponent;
import pro.gravit.launchserver.components.Component; import pro.gravit.launchserver.components.Component;
import pro.gravit.launchserver.components.RegLimiterComponent;
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig; import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
import pro.gravit.launchserver.dao.UserService; import pro.gravit.launchserver.dao.UserService;
import pro.gravit.launchserver.dao.provider.DaoProvider; import pro.gravit.launchserver.dao.provider.DaoProvider;
@ -761,6 +762,11 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
authLimiterComponent.rateLimitMilis = 8000; authLimiterComponent.rateLimitMilis = 8000;
authLimiterComponent.message = "Превышен лимит авторизаций"; authLimiterComponent.message = "Превышен лимит авторизаций";
newConfig.components.put("authLimiter", authLimiterComponent); newConfig.components.put("authLimiter", authLimiterComponent);
RegLimiterComponent regLimiterComponent = new RegLimiterComponent();
regLimiterComponent.rateLimit = 3;
regLimiterComponent.rateLimitMilis = 1000 * 60 * 60 * 10; //Блок на 10 часов
regLimiterComponent.message = "Превышен лимит регистраций";
newConfig.components.put("regLimiter", regLimiterComponent);
// Set server address // Set server address
String address; String address;

View file

@ -4,6 +4,7 @@
import pro.gravit.launchserver.auth.AuthException; import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.dao.User; import pro.gravit.launchserver.dao.User;
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
import pro.gravit.utils.helper.SecurityHelper; import pro.gravit.utils.helper.SecurityHelper;
public class HibernateAuthProvider extends AuthProvider { public class HibernateAuthProvider extends AuthProvider {
@ -13,7 +14,15 @@ public AuthProviderResult auth(String login, String password, String ip) throws
User user = srv.config.dao.userService.findUserByUsername(login); User user = srv.config.dao.userService.findUserByUsername(login);
if(user == null && autoReg) if(user == null && autoReg)
{ {
user = srv.config.dao.userService.registerNewUser(login, password); AuthHookManager.RegContext context = new AuthHookManager.RegContext(login, password, ip, false);
if(AuthHookManager.registraion.hook(context))
{
user = srv.config.dao.userService.registerNewUser(login, password);
}
else
{
throw new AuthException("Registration canceled. Try again later");
}
} }
if(user == null || !user.verifyPassword(password)) if(user == null || !user.verifyPassword(password))
{ {

View file

@ -10,6 +10,7 @@ public abstract class Component {
public static void registerComponents() { public static void registerComponents() {
if (!registredComp) { if (!registredComp) {
providers.register("authLimiter", AuthLimiterComponent.class); providers.register("authLimiter", AuthLimiterComponent.class);
providers.register("regLimiter", RegLimiterComponent.class);
providers.register("commandRemover", CommandRemoverComponent.class); providers.register("commandRemover", CommandRemoverComponent.class);
registredComp = true; registredComp = true;
} }

View file

@ -0,0 +1,76 @@
package pro.gravit.launchserver.components;
import pro.gravit.launcher.NeedGarbageCollection;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
import pro.gravit.utils.HookException;
import pro.gravit.utils.HookSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class RegLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable {
public static final long TIMEOUT = 12 * 60 * 60 * 1000; //12 часов
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) {
this.launchServer = launchServer;
}
@Override
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;
});
}
@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;
}
map.put(ip, new AuthLimiterComponent.AuthEntry(1, System.currentTimeMillis()));
return false;
}
@Override
public void close() throws Exception {
if(hook != null)
launchServer.authHookManager.registraion.unregisterHook(hook);
}
}

View file

@ -6,6 +6,7 @@
import pro.gravit.launchserver.socket.response.auth.JoinServerResponse; import pro.gravit.launchserver.socket.response.auth.JoinServerResponse;
import pro.gravit.launchserver.socket.response.auth.SetProfileResponse; import pro.gravit.launchserver.socket.response.auth.SetProfileResponse;
import pro.gravit.utils.BiHookSet; import pro.gravit.utils.BiHookSet;
import pro.gravit.utils.HookSet;
public class AuthHookManager { public class AuthHookManager {
public BiHookSet<AuthResponse.AuthContext, Client> preHook = new BiHookSet<>(); public BiHookSet<AuthResponse.AuthContext, Client> preHook = new BiHookSet<>();
@ -13,4 +14,18 @@ public class AuthHookManager {
public BiHookSet<CheckServerResponse, Client> checkServerHook = new BiHookSet<>(); public BiHookSet<CheckServerResponse, Client> checkServerHook = new BiHookSet<>();
public BiHookSet<JoinServerResponse, Client> joinServerHook = new BiHookSet<>(); public BiHookSet<JoinServerResponse, Client> joinServerHook = new BiHookSet<>();
public BiHookSet<SetProfileResponse, Client> setProfileHook = new BiHookSet<>(); public BiHookSet<SetProfileResponse, Client> setProfileHook = new BiHookSet<>();
public static class RegContext
{
public String login;
public String password;
public String ip;
public boolean trustContext;
public RegContext(String login, String password, String ip, boolean trustContext) {
this.login = login;
this.password = password;
this.ip = ip;
this.trustContext = trustContext;
}
}
public HookSet<RegContext> registraion;
} }