diff --git a/.travis.yml b/.travis.yml index 5b16bd95..5036a346 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,8 @@ sudo: false # This is a java project language: java -script: mvn compile test +script: mvn test -B -jdk: [oraclejdk8] +jdk: + - oraclejdk8 + - oraclejdk9 diff --git a/README.md b/README.md index 19966107..64982943 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ So they don't need to enter passwords. This is also called auto login (auto-logi ### Requirements: * Plugin: [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/) -* Tested [Spigot](https://www.spigotmc.org) 1.8+ (could also work with other versions) +* [Spigot](https://www.spigotmc.org) 1.7+ * Java 8+ * Run Spigot and/or BungeeCord/Waterfall in offline mode (see server.properties or config.yml) * An auth plugin. Supported plugins diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java index 573ec2df..d85b07c3 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java @@ -27,6 +27,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.messaging.PluginMessageRecipient; +import org.slf4j.Logger; /** * This plugin checks if a player has a paid account and if so tries to skip offline mode authentication. @@ -35,6 +36,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin core; @@ -52,12 +54,12 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin addresses, int requests, List proxies) { - return new MojangApiBukkit(getLogger(), addresses, requests, proxies); + return new MojangApiBukkit(getLog(), addresses, requests, proxies); } } diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/MojangApiBukkit.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/MojangApiBukkit.java index bcd5a120..bef6f511 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/MojangApiBukkit.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/MojangApiBukkit.java @@ -13,14 +13,14 @@ import java.net.InetSocketAddress; import java.net.URLEncoder; import java.util.Collection; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; + +import org.slf4j.Logger; public class MojangApiBukkit extends MojangApiConnector { //mojang api check to prove a player is logged in minecraft and made a join server request private static final String HAS_JOINED_URL = "https://sessionserver.mojang.com/session/minecraft/hasJoined?" + - "username=%s&serverId=%s"; + "username=%s&serverId=%s&ip=%s"; public MojangApiBukkit(Logger logger, Collection localAddresses, int rateLimit , List proxies) { @@ -31,11 +31,9 @@ public class MojangApiBukkit extends MojangApiConnector { public boolean hasJoinedServer(LoginSession session, String serverId, InetSocketAddress ip) { BukkitLoginSession playerSession = (BukkitLoginSession) session; - String url = String.format(HAS_JOINED_URL, playerSession.getUsername(), serverId); try { - if (ip != null) { - url += "&ip=" + URLEncoder.encode(ip.getAddress().getHostAddress(), "UTF-8"); - } + String encodedIp = URLEncoder.encode(ip.getAddress().getHostAddress(), "UTF-8"); + String url = String.format(HAS_JOINED_URL, playerSession.getUsername(), serverId, encodedIp); HttpURLConnection conn = getConnection(url); @@ -55,7 +53,7 @@ public class MojangApiBukkit extends MojangApiConnector { } } catch (Exception ex) { //catch not only io-exceptions also parse and NPE on unexpected json format - logger.log(Level.WARNING, "Failed to verify session", ex); + logger.warn("Failed to verify session", ex); } //this connection doesn't need to be closed. So can make use of keep alive in java diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java index f874fe2e..9978461c 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/BungeeListener.java @@ -14,7 +14,6 @@ import java.nio.file.Path; import java.util.Collections; import java.util.Set; import java.util.UUID; -import java.util.logging.Level; import java.util.stream.Collectors; import org.bukkit.Bukkit; @@ -48,20 +47,19 @@ public class BungeeListener implements PluginMessageListener { ByteArrayDataInput dataInput = ByteStreams.newDataInput(message); String subChannel = dataInput.readUTF(); - plugin.getLogger().log(Level.FINEST, "Received plugin message for sub channel {0} from {1}" - , new Object[]{subChannel, player}); + plugin.getLog().debug("Received plugin message for sub channel {} from {}", subChannel, player); String playerName = dataInput.readUTF(); //check if the player is still online or disconnected - Player checkedPlayer = plugin.getServer().getPlayerExact(playerName); + Player checkedPlayer = Bukkit.getPlayerExact(playerName); //fail if target player is blacklisted because already authenticated or wrong bungeecord id if (checkedPlayer != null && !checkedPlayer.hasMetadata(plugin.getName())) { //bungeecord UUID long mostSignificantBits = dataInput.readLong(); long leastSignificantBits = dataInput.readLong(); UUID sourceId = new UUID(mostSignificantBits, leastSignificantBits); - plugin.getLogger().log(Level.FINEST, "Received proxy id {0} from {1}", new Object[]{sourceId, player}); + plugin.getLog().debug("Received proxy id {} from {}", sourceId, player); //fail if BungeeCord support is disabled (id = null) if (proxyIds.contains(sourceId)) { @@ -90,7 +88,7 @@ public class BungeeListener implements PluginMessageListener { new ForceLoginTask(plugin.getCore(), player).run(); } } catch (Exception ex) { - plugin.getLogger().log(Level.SEVERE, "Failed to query isRegistered", ex); + plugin.getLog().error("Failed to query isRegistered", ex); } }); } @@ -108,9 +106,9 @@ public class BungeeListener implements PluginMessageListener { .map(UUID::fromString) .collect(Collectors.toSet()); } catch (IOException ex) { - plugin.getLogger().log(Level.SEVERE, "Failed to create file for Proxy whitelist", ex); + plugin.getLog().error("Failed to create file for Proxy whitelist", ex); } catch (Exception ex) { - plugin.getLogger().log(Level.SEVERE, "Failed to retrieve proxy Id. Disabling BungeeCord support", ex); + plugin.getLog().error("Failed to retrieve proxy Id. Disabling BungeeCord support", ex); } return Collections.emptySet(); diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/LoginSkinApplyListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/LoginSkinApplyListener.java index 663a42d4..ab730915 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/LoginSkinApplyListener.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/LoginSkinApplyListener.java @@ -11,7 +11,6 @@ import com.github.games647.fastlogin.bukkit.FastLoginBukkit; import com.github.games647.fastlogin.core.mojang.SkinProperties; import java.lang.reflect.InvocationTargetException; -import java.util.logging.Level; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -65,7 +64,7 @@ public class LoginSkinApplyListener implements Listener { try { MethodUtils.invokeMethod(map, "put", new Object[]{"textures", skin.getHandle()}); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) { - plugin.getLogger().log(Level.SEVERE, "Error setting premium skin", ex); + plugin.getLog().error("Error setting premium skin", ex); } } } diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/NameCheckTask.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/NameCheckTask.java index 2f0cf1f9..d207444b 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/NameCheckTask.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/NameCheckTask.java @@ -8,7 +8,6 @@ import com.github.games647.fastlogin.core.PlayerProfile; import com.github.games647.fastlogin.core.shared.JoinManagement; import java.util.Random; -import java.util.logging.Level; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -50,7 +49,7 @@ public class NameCheckTask extends JoinManagement> clazz : supportedHooks) { String pluginName = clazz.getSimpleName().replace("Hook", ""); //uses only member classes which uses AuthPlugin interface (skip interfaces) - if (Bukkit.getServer().getPluginManager().isPluginEnabled(pluginName)) { + if (Bukkit.getPluginManager().isPluginEnabled(pluginName)) { //check only for enabled plugins. A single plugin could be disabled by plugin managers authPluginHook = clazz.newInstance(); - plugin.getLogger().log(Level.INFO, "Hooking into auth plugin: {0}", pluginName); + plugin.getLog().info("Hooking into auth plugin: {}", pluginName); break; } } } catch (InstantiationException | IllegalAccessException ex) { - plugin.getLogger().log(Level.SEVERE, "Couldn't load the integration class", ex); + plugin.getLog().error("Couldn't load the integration class", ex); } if (authPluginHook == null) { //run this check for exceptions (errors) and not found plugins - plugin.getLogger().warning("No support offline Auth plugin found. "); + plugin.getLog().warn("No support offline Auth plugin found. "); return false; } diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/tasks/ForceLoginTask.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/tasks/ForceLoginTask.java index 18df4f27..f80e4c90 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/tasks/ForceLoginTask.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/tasks/ForceLoginTask.java @@ -9,7 +9,6 @@ import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import java.util.concurrent.ExecutionException; -import java.util.logging.Level; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; @@ -56,7 +55,7 @@ public class ForceLoginTask extends ForceLoginManagement { private final ConcurrentMap session = Maps.newConcurrentMap(); + private final Logger logger = CommonUtil.createLoggerFromJDK(getLogger()); private FastLoginCore core; @@ -66,7 +70,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin addresses, int requests, List proxies) { - return new MojangApiConnector(getLogger(), addresses, requests, proxies); + return new MojangApiConnector(getLog(), addresses, requests, proxies); } } diff --git a/bungee/src/main/java/com/github/games647/fastlogin/bungee/listener/ConnectListener.java b/bungee/src/main/java/com/github/games647/fastlogin/bungee/listener/ConnectListener.java index fe27444c..4bc6fee7 100644 --- a/bungee/src/main/java/com/github/games647/fastlogin/bungee/listener/ConnectListener.java +++ b/bungee/src/main/java/com/github/games647/fastlogin/bungee/listener/ConnectListener.java @@ -9,7 +9,6 @@ import com.google.common.base.Charsets; import java.lang.reflect.Field; import java.util.UUID; -import java.util.logging.Level; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.connection.PendingConnection; @@ -82,7 +81,7 @@ public class ConnectListener implements Listener { idField.setAccessible(true); idField.set(connection, offlineUUID); } catch (NoSuchFieldException | IllegalAccessException ex) { - plugin.getLogger().log(Level.SEVERE, "Failed to set offline uuid", ex); + plugin.getLog().error("Failed to set offline uuid", ex); } } diff --git a/core/src/main/java/com/github/games647/fastlogin/core/AuthStorage.java b/core/src/main/java/com/github/games647/fastlogin/core/AuthStorage.java index 974767f5..fcd08560 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/AuthStorage.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/AuthStorage.java @@ -13,7 +13,6 @@ import java.sql.Statement; import java.util.Properties; import java.util.UUID; import java.util.concurrent.ThreadFactory; -import java.util.logging.Level; public class AuthStorage { @@ -104,7 +103,7 @@ public class AuthStorage { } } } catch (SQLException sqlEx) { - core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx); + core.getPlugin().getLog().error("Failed to query profile", sqlEx); } return null; @@ -128,7 +127,7 @@ public class AuthStorage { } } } catch (SQLException sqlEx) { - core.getPlugin().getLogger().log(Level.SEVERE, "Failed to query profile", sqlEx); + core.getPlugin().getLog().error("Failed to query profile", sqlEx); } return null; @@ -179,7 +178,7 @@ public class AuthStorage { return true; } catch (SQLException ex) { - core.getPlugin().getLogger().log(Level.SEVERE, "Failed to save playerProfile", ex); + core.getPlugin().getLog().error("Failed to save playerProfile", ex); } return false; diff --git a/core/src/main/java/com/github/games647/fastlogin/core/CommonUtil.java b/core/src/main/java/com/github/games647/fastlogin/core/CommonUtil.java index 6f3c851f..adb03fd4 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/CommonUtil.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/CommonUtil.java @@ -2,9 +2,15 @@ package com.github.games647.fastlogin.core; import com.google.common.cache.CacheLoader; +import java.lang.reflect.Constructor; import java.util.UUID; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.impl.JDK14LoggerAdapter; public class CommonUtil { @@ -47,6 +53,19 @@ public class CommonUtil { return new String(chars); } + public static Logger createLoggerFromJDK(java.util.logging.Logger parent) { + try { + Class adapterClass = JDK14LoggerAdapter.class; + Constructor cons = adapterClass.getDeclaredConstructor(java.util.logging.Logger.class); + cons.setAccessible(true); + return cons.newInstance(parent); + } catch (ReflectiveOperationException reflectEx) { + parent.log(Level.WARNING, "Cannot create slf4j logging adapter", reflectEx); + parent.log(Level.WARNING, "Creating logger instance manually..."); + return LoggerFactory.getLogger(parent.getName()); + } + } + private CommonUtil() { //Utility class } diff --git a/core/src/main/java/com/github/games647/fastlogin/core/mojang/MojangApiConnector.java b/core/src/main/java/com/github/games647/fastlogin/core/mojang/MojangApiConnector.java index bb5869d0..5b87e259 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/mojang/MojangApiConnector.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/mojang/MojangApiConnector.java @@ -27,24 +27,23 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.regex.Pattern; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSocketFactory; +import org.slf4j.Logger; + public class MojangApiConnector { //http connection, read timeout and user agent for a connection to mojang api servers private static final int TIMEOUT = 3 * 1_000; private static final String USER_AGENT = "Premium-Checker"; + private static final int RATE_LIMIT_CODE = 429; //only premium (paid account) users have a uuid from here private static final String UUID_LINK = "https://api.mojang.com/users/profiles/minecraft/"; - private static final int RATE_LIMIT_CODE = 429; - //this includes a-zA-Z1-9_ //compile the pattern only on plugin enable -> and this have to be thread-safe private final Pattern validNameMatcher = Pattern.compile("^\\w{2,16}$"); @@ -53,6 +52,7 @@ public class MojangApiConnector { private final Map requests = CommonUtil.buildCache(10, -1); private final SSLSocketFactory sslFactory; private final int rateLimit; + private long lastRateLimit; protected final Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create(); @@ -110,7 +110,7 @@ public class MojangApiConnector { } //204 - no content for not found } catch (Exception ex) { - logger.log(Level.SEVERE, "Failed to check if player has a paid account", ex); + logger.error("Failed to check if player has a paid account", ex); } return Optional.empty(); @@ -161,13 +161,13 @@ public class MojangApiConnector { try { InetAddress address = InetAddress.getByName(localAddress); if (!address.isAnyLocalAddress()) { - logger.log(Level.WARNING, "Submitted IP-Address is not local {0}", address); + logger.warn("Submitted IP-Address is not local {0}", address); continue; } addresses.add(address); } catch (UnknownHostException ex) { - logger.log(Level.SEVERE, "IP-Address is unknown to us", ex); + logger.error("IP-Address is unknown to us", ex); } } diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/FastLoginCore.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/FastLoginCore.java index 7c39c8d0..253dd19d 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/FastLoginCore.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/FastLoginCore.java @@ -23,7 +23,6 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; -import java.util.logging.Level; import java.util.stream.Collectors; import net.md_5.bungee.config.Configuration; @@ -72,7 +71,7 @@ public class FastLoginCore

> { } }); } catch (IOException ioEx) { - plugin.getLogger().log(Level.INFO, "Failed to load yaml files", ioEx); + plugin.getLog().error("Failed to load yaml files", ioEx); } List ipAddresses = config.getStringList("ip-addresses"); @@ -134,7 +133,7 @@ public class FastLoginCore

> { storage.createTables(); return true; } catch (Exception ex) { - plugin.getLogger().log(Level.SEVERE, "Failed to setup database. Disabling plugin...", ex); + plugin.getLog().warn("Failed to setup database. Disabling plugin...", ex); return false; } } @@ -180,7 +179,7 @@ public class FastLoginCore

> { } } } catch (IOException ioExc) { - plugin.getLogger().log(Level.SEVERE, "Cannot create plugin folder " + dataFolder, ioExc); + plugin.getLog().error("Cannot create plugin folder {}", dataFolder, ioExc); } } diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/ForceLoginManagement.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/ForceLoginManagement.java index 3bc2f5cc..ea874286 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/ForceLoginManagement.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/ForceLoginManagement.java @@ -4,8 +4,6 @@ import com.github.games647.fastlogin.core.AuthStorage; import com.github.games647.fastlogin.core.PlayerProfile; import com.github.games647.fastlogin.core.hooks.AuthPlugin; -import java.util.logging.Level; - public abstract class ForceLoginManagement

> implements Runnable { @@ -66,12 +64,12 @@ public abstract class ForceLoginManagement

{ try { if (profile.getUserId() == -1) { if (core.getPendingLogin().remove(ip + username) != null && config.get("secondAttemptCracked", false)) { - core.getPlugin().getLogger().log(Level.INFO, "Second attempt login -> cracked {0}", username); + core.getPlugin().getLog().info("Second attempt login -> cracked {}", username); //first login request failed so make a cracked session startCrackedSession(source, profile, username); @@ -61,12 +60,12 @@ public abstract class JoinManagement

{ startCrackedSession(source, profile, username); } } catch (Exception ex) { - core.getPlugin().getLogger().log(Level.SEVERE, "Failed to check premium state", ex); + core.getPlugin().getLog().error("Failed to check premium state", ex); } } private boolean checkPremiumName(S source, String username, PlayerProfile profile) throws Exception { - core.getPlugin().getLogger().log(Level.FINER, "GameProfile {0} uses a premium username", username); + core.getPlugin().getLog().debug("GameProfile {} uses a premium username", username); if (core.getConfig().get("autoRegister", false) && (authHook == null || !authHook.isRegistered(username))) { requestPremiumLogin(source, profile, username, false); return true; @@ -81,7 +80,7 @@ public abstract class JoinManagement

{ PlayerProfile profile = core.getStorage().loadProfile(premiumUUID); if (profile != null) { //uuid exists in the database - core.getPlugin().getLogger().log(Level.FINER, "GameProfile {0} changed it's username", premiumUUID); + core.getPlugin().getLog().info("GameProfile {} changed it's username", premiumUUID); //update the username to the new one in the database profile.setPlayerName(username); diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/PlatformPlugin.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/PlatformPlugin.java index 9dba7f05..8e90bd8a 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/PlatformPlugin.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/PlatformPlugin.java @@ -6,7 +6,8 @@ import com.google.common.net.HostAndPort; import java.io.File; import java.util.List; import java.util.concurrent.ThreadFactory; -import java.util.logging.Logger; + +import org.slf4j.Logger; public interface PlatformPlugin { @@ -14,7 +15,7 @@ public interface PlatformPlugin { File getDataFolder(); - Logger getLogger(); + Logger getLog(); void sendMessage(C receiver, String message);