Thermos supports GSON so we could share the json parsing

This commit is contained in:
games647
2017-09-22 18:17:35 +02:00
parent 109508dae6
commit bb80521ab6
12 changed files with 103 additions and 101 deletions

View File

@ -9,7 +9,7 @@ import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibList
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
import com.github.games647.fastlogin.bukkit.tasks.DelayedAuthHook;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.google.common.collect.Iterables;
import com.google.common.io.ByteArrayDataOutput;

View File

@ -1,8 +1,10 @@
package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
import com.github.games647.fastlogin.core.mojang.SkinProperties;
import com.github.games647.fastlogin.core.mojang.VerificationReply;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
import java.io.BufferedReader;
import java.io.InputStreamReader;
@ -14,10 +16,6 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
public class MojangApiBukkit extends MojangApiConnector {
//mojang api check to prove a player is logged in minecraft and made a join server request
@ -42,26 +40,23 @@ public class MojangApiBukkit extends MojangApiConnector {
HttpURLConnection conn = getConnection(url);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String line = reader.readLine();
if (line != null && !"null".equals(line)) {
//validate parsing
//http://wiki.vg/Protocol_Encryption#Server
JSONObject userData = (JSONObject) JSONValue.parseWithException(line);
String uuid = (String) userData.get("id");
playerSession.setUuid(FastLoginCore.parseId(uuid));
//validate parsing
//http://wiki.vg/Protocol_Encryption#Server
VerificationReply verification = gson.fromJson(reader, VerificationReply.class);
JSONArray properties = (JSONArray) userData.get("properties");
JSONObject skinProperty = (JSONObject) properties.get(0);
String uuid = verification.getId();
playerSession.setUuid(FastLoginCore.parseId(uuid));
String propertyName = (String) skinProperty.get("name");
if ("textures".equals(propertyName)) {
String skinValue = (String) skinProperty.get("value");
String signature = (String) skinProperty.get("signature");
playerSession.setSkin(skinValue, signature);
}
SkinProperties[] properties = verification.getProperties();
if (properties != null && properties.length > 0) {
SkinProperties skinProperty = properties[0];
return true;
String skinValue = skinProperty.getValue();
String signature = skinProperty.getSignature();
playerSession.setSkin(skinValue, signature);
}
return true;
}
} catch (Exception ex) {
//catch not only io-exceptions also parse and NPE on unexpected json format
@ -71,24 +66,4 @@ public class MojangApiBukkit extends MojangApiConnector {
//this connection doesn't need to be closed. So can make use of keep alive in java
return false;
}
@Override
protected String getUUIDFromJson(String json) {
boolean isArray = json.startsWith("[");
JSONObject mojangPlayer;
if (isArray) {
JSONArray array = (JSONArray) JSONValue.parse(json);
mojangPlayer = (JSONObject) array.get(0);
} else {
mojangPlayer = (JSONObject) JSONValue.parse(json);
}
String uuid = (String) mojangPlayer.get("id");
if ("null".equals(uuid)) {
return null;
}
return uuid;
}
}

View File

@ -15,7 +15,7 @@ public class EncryptionUtilTest {
byte[] token = EncryptionUtil.generateVerifyToken(random);
assertNotNull(token);
assertEquals(token.length, 4);
assertEquals(4, token.length);
}
// @Test

View File

@ -4,7 +4,7 @@ import com.github.games647.fastlogin.bungee.hooks.BungeeAuthHook;
import com.github.games647.fastlogin.bungee.listener.ConnectionListener;
import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
import com.google.common.collect.Maps;
@ -111,6 +111,6 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
@Override
public MojangApiConnector makeApiConnector(Logger logger, List<String> addresses, int requests
, Map<String, Integer> proxies) {
return new MojangApiBungee(logger, addresses, requests, proxies);
return new MojangApiConnector(logger, addresses, requests, proxies);
}
}

View File

@ -1,44 +0,0 @@
package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.github.games647.fastlogin.core.shared.MojangApiConnector;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Map;
import java.util.logging.Logger;
import net.md_5.bungee.BungeeCord;
public class MojangApiBungee extends MojangApiConnector {
public MojangApiBungee(Logger logger, Collection<String> localAddresses, int rateLimit
, Map<String, Integer> proxies) {
super(logger, localAddresses, rateLimit, proxies);
}
@Override
protected String getUUIDFromJson(String json) {
boolean isArray = json.startsWith("[");
MojangPlayer mojangPlayer;
if (isArray) {
mojangPlayer = BungeeCord.getInstance().gson.fromJson(json, MojangPlayer[].class)[0];
} else {
mojangPlayer = BungeeCord.getInstance().gson.fromJson(json, MojangPlayer.class);
}
String id = mojangPlayer.getId();
if ("null".equals(id)) {
return null;
}
return id;
}
@Override
public boolean hasJoinedServer(LoginSession session, String serverId, InetSocketAddress ip) {
//this is not needed in Bungee
throw new UnsupportedOperationException("Not supported");
}
}

View File

@ -35,5 +35,12 @@
<version>10.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,9 +1,12 @@
package com.github.games647.fastlogin.core.shared;
package com.github.games647.fastlogin.core.mojang;
import com.github.games647.fastlogin.core.BalancedSSLFactory;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSession;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.IOException;
@ -22,14 +25,13 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.net.ssl.HttpsURLConnection;
public abstract class MojangApiConnector {
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;
@ -37,20 +39,20 @@ public abstract class MojangApiConnector {
//only premium (paid account) users have a uuid from here
private static final String UUID_LINK = "https://api.mojang.com/users/profiles/minecraft/";
//this includes a-zA-Z1-9_
private static final String VALID_PLAYERNAME = "^\\w{2,16}$";
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 nameMatcher = Pattern.compile(VALID_PLAYERNAME);
private final Pattern validNameMatcher = Pattern.compile("^\\w{2,16}$");
private final Iterator<Proxy> proxies;
private final ConcurrentMap<Object, Object> requests = FastLoginCore.buildCache(10, -1);
private final Map<Object, Object> requests = FastLoginCore.buildCache(10, -1);
private final BalancedSSLFactory sslFactory;
private final int rateLimit;
private long lastRateLimit;
protected final Gson gson = new Gson();
protected final Logger logger;
public MojangApiConnector(Logger logger, Collection<String> localAddresses, int rateLimit
@ -71,7 +73,7 @@ public abstract class MojangApiConnector {
* @return null on non-premium
*/
public UUID getPremiumUUID(String playerName) {
if (!nameMatcher.matcher(playerName).matches()) {
if (!validNameMatcher.matcher(playerName).matches()) {
//check if it's a valid player name
return null;
}
@ -113,9 +115,28 @@ public abstract class MojangApiConnector {
return null;
}
public abstract boolean hasJoinedServer(LoginSession session, String serverId, InetSocketAddress ip);
public boolean hasJoinedServer(LoginSession session, String serverId, InetSocketAddress ip) {
//only available in Spigot and not in BungeeCord
return false;
}
protected abstract String getUUIDFromJson(String json);
private String getUUIDFromJson(String json) {
boolean isArray = json.startsWith("[");
Player mojangPlayer;
if (isArray) {
mojangPlayer = gson.fromJson(json, Player[].class)[0];
} else {
mojangPlayer = gson.fromJson(json, Player.class);
}
String id = mojangPlayer.getId();
if ("null".equals(id)) {
return null;
}
return id;
}
protected HttpsURLConnection getConnection(String url, Proxy proxy) throws IOException {
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(proxy);

View File

@ -1,6 +1,6 @@
package com.github.games647.fastlogin.bungee;
package com.github.games647.fastlogin.core.mojang;
public class MojangPlayer {
public class Player {
private String id;
private String name;

View File

@ -0,0 +1,20 @@
package com.github.games647.fastlogin.core.mojang;
public class SkinProperties {
private String name;
private String value;
private String signature;
public String getName() {
return name;
}
public String getValue() {
return value;
}
public String getSignature() {
return signature;
}
}

View File

@ -0,0 +1,20 @@
package com.github.games647.fastlogin.core.mojang;
public class VerificationReply {
private String id;
private String name;
private SkinProperties[] properties;
public String getId() {
return id;
}
public String getName() {
return name;
}
public SkinProperties[] getProperties() {
return properties;
}
}

View File

@ -6,6 +6,7 @@ import com.github.games647.fastlogin.core.SharedConfig;
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.hooks.DefaultPasswordGenerator;
import com.github.games647.fastlogin.core.hooks.PasswordGenerator;
import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

View File

@ -1,5 +1,7 @@
package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
import java.io.File;
import java.io.Reader;
import java.util.List;