aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Ilin <hevav@hevav.dev>2022-04-02 11:28:16 +0300
committerPetr Ilin <hevav@hevav.dev>2022-04-02 11:28:16 +0300
commit1c63ce46241e8df6f35f33533b808184811863ca (patch)
treef60d791e41c97012c1e18c88bed0593d3b7a24ff
parent757ab79b96b0b6d784fa113a496f56e52f59c88a (diff)
downloadLimboAuth-1c63ce46241e8df6f35f33533b808184811863ca.tar.gz
LimboAuth-1c63ce46241e8df6f35f33533b808184811863ca.tar.bz2
LimboAuth-1c63ce46241e8df6f35f33533b808184811863ca.zip
Better premium/cracked detection+caching (closes #15, closes #19)
-rw-r--r--src/main/java/net/elytrium/limboauth/LimboAuth.java75
-rw-r--r--src/main/java/net/elytrium/limboauth/Settings.java8
2 files changed, 70 insertions, 13 deletions
diff --git a/src/main/java/net/elytrium/limboauth/LimboAuth.java b/src/main/java/net/elytrium/limboauth/LimboAuth.java
index b92ec91..c1b63d1 100644
--- a/src/main/java/net/elytrium/limboauth/LimboAuth.java
+++ b/src/main/java/net/elytrium/limboauth/LimboAuth.java
@@ -114,7 +114,8 @@ import org.slf4j.Logger;
)
public class LimboAuth {
- private final Map<String, CachedUser> cachedAuthChecks = new ConcurrentHashMap<>();
+ private final Map<String, CachedSessionUser> cachedAuthChecks = new ConcurrentHashMap<>();
+ private final Map<String, CachedPremiumUser> premiumCache = new ConcurrentHashMap<>();
private final Map<UUID, Runnable> postLoginTasks = new ConcurrentHashMap<>();
private final Set<String> unsafePasswords = new HashSet<>();
@@ -286,12 +287,19 @@ public class LimboAuth {
this.server.getEventManager().register(this, new AuthListener(this, this.playerDao, this.floodgateApi));
Executors.newScheduledThreadPool(1, task -> new Thread(task, "purge-cache")).scheduleAtFixedRate(() ->
- this.checkCache(this.cachedAuthChecks, Settings.IMP.MAIN.PURGE_CACHE_MILLIS),
+ this.checkCache(this.cachedAuthChecks, Settings.IMP.MAIN.PURGE_CACHE_MILLIS),
Settings.IMP.MAIN.PURGE_CACHE_MILLIS,
Settings.IMP.MAIN.PURGE_CACHE_MILLIS,
TimeUnit.MILLISECONDS
);
+ Executors.newScheduledThreadPool(1, task -> new Thread(task, "purge-premium-cache")).scheduleAtFixedRate(() ->
+ this.checkCache(this.premiumCache, Settings.IMP.MAIN.PURGE_PREMIUM_CACHE_MILLIS),
+ Settings.IMP.MAIN.PURGE_PREMIUM_CACHE_MILLIS,
+ Settings.IMP.MAIN.PURGE_PREMIUM_CACHE_MILLIS,
+ TimeUnit.MILLISECONDS
+ );
+
this.server.getEventManager().fireAndForget(new AuthPluginReloadEvent());
}
@@ -355,7 +363,7 @@ public class LimboAuth {
public void cacheAuthUser(Player player) {
String username = player.getUsername().toLowerCase(Locale.ROOT);
this.cachedAuthChecks.remove(username);
- this.cachedAuthChecks.put(username, new CachedUser(player.getRemoteAddress().getAddress(), System.currentTimeMillis()));
+ this.cachedAuthChecks.put(username, new CachedSessionUser(player.getRemoteAddress().getAddress(), System.currentTimeMillis()));
}
public void removePlayerFromCache(String username) {
@@ -465,16 +473,35 @@ public class LimboAuth {
}
public boolean isPremiumExternal(String nickname) {
+ String lowercaseNickname = nickname.toLowerCase(Locale.ROOT);
+ if (this.premiumCache.containsKey(lowercaseNickname)) {
+ return this.premiumCache.get(lowercaseNickname).isPremium();
+ }
+
try {
- return this.client.send(
+ int statusCode = this.client.send(
HttpRequest.newBuilder()
- .uri(URI.create(String.format(Settings.IMP.MAIN.ISPREMIUM_AUTH_URL, URLEncoder.encode(nickname, StandardCharsets.UTF_8))))
+ .uri(URI.create(
+ String.format(
+ Settings.IMP.MAIN.ISPREMIUM_AUTH_URL,
+ URLEncoder.encode(lowercaseNickname, StandardCharsets.UTF_8))))
.build(),
HttpResponse.BodyHandlers.ofString()
- ).statusCode() == 200;
+ ).statusCode();
+
+ boolean isPremium = statusCode == 200;
+
+ // 429 Too Many Requests
+ if (statusCode != 429) {
+ this.premiumCache.put(lowercaseNickname, new CachedPremiumUser(isPremium, System.currentTimeMillis()));
+ } else {
+ return Settings.IMP.MAIN.ON_RATE_LIMIT_PREMIUM;
+ }
+
+ return isPremium;
} catch (IOException | InterruptedException e) {
this.getLogger().error("Unable to authenticate with Mojang", e);
- return true;
+ return Settings.IMP.MAIN.ON_RATE_LIMIT_PREMIUM;
}
}
@@ -513,7 +540,7 @@ public class LimboAuth {
}
}
- private void checkCache(Map<String, CachedUser> userMap, long time) {
+ private void checkCache(Map<String, ? extends CachedUser> userMap, long time) {
userMap.entrySet().stream()
.filter(u -> u.getValue().getCheckTime() + time <= System.currentTimeMillis())
.map(Map.Entry::getKey)
@@ -546,20 +573,42 @@ public class LimboAuth {
private static class CachedUser {
- private final InetAddress inetAddress;
private final long checkTime;
- public CachedUser(InetAddress inetAddress, long checkTime) {
- this.inetAddress = inetAddress;
+ public CachedUser(long checkTime) {
this.checkTime = checkTime;
}
+ public long getCheckTime() {
+ return this.checkTime;
+ }
+ }
+
+ private static class CachedSessionUser extends CachedUser {
+
+ private final InetAddress inetAddress;
+
+ public CachedSessionUser(InetAddress inetAddress, long checkTime) {
+ super(checkTime);
+ this.inetAddress = inetAddress;
+ }
+
public InetAddress getInetAddress() {
return this.inetAddress;
}
+ }
- public long getCheckTime() {
- return this.checkTime;
+ private static class CachedPremiumUser extends CachedUser {
+
+ private final boolean isPremium;
+
+ public CachedPremiumUser(boolean isPremium, long checkTime) {
+ super(checkTime);
+ this.isPremium = isPremium;
+ }
+
+ public boolean isPremium() {
+ return this.isPremium;
}
}
diff --git a/src/main/java/net/elytrium/limboauth/Settings.java b/src/main/java/net/elytrium/limboauth/Settings.java
index 745a6ee..0ce9186 100644
--- a/src/main/java/net/elytrium/limboauth/Settings.java
+++ b/src/main/java/net/elytrium/limboauth/Settings.java
@@ -90,6 +90,7 @@ public class Settings extends Config {
@Comment("Available dimensions: OVERWORLD, NETHER, THE_END")
public String DIMENSION = "THE_END";
public long PURGE_CACHE_MILLIS = 3600000;
+ public long PURGE_PREMIUM_CACHE_MILLIS = 28800000;
@Comment("QR Generator URL, set {data} placeholder")
public String QR_GENERATOR_URL = "https://api.qrserver.com/v1/create-qr-code/?data={data}&size=200x200&ecc=M&margin=30";
public String TOTP_ISSUER = "LimboAuth by Elytrium";
@@ -120,6 +121,13 @@ public class Settings extends Config {
})
public String ISPREMIUM_AUTH_URL = "https://api.mojang.com/users/profiles/minecraft/%s";
+ @Comment({
+ "If Mojang rate-limits your server, we cannot determine if the player is premium or not",
+ "This option allows you to choose whether every player will be defined as premium or as cracked while Mojang is rate-limiting the server",
+ "True - as premium; False - as cracked"
+ })
+ public boolean ON_RATE_LIMIT_PREMIUM = true;
+
public List<String> REGISTER_COMMAND = List.of("/r", "/reg", "/register");
public List<String> LOGIN_COMMAND = List.of("/l", "/log", "/login");
public List<String> TOTP_COMMAND = List.of("/2fa", "/totp");