forked from TuxCoding/FastLogin
Use Gson's TypeAdapter for more type safety
This commit is contained in:
@ -1,5 +1,9 @@
|
|||||||
### 1.11
|
### 1.11
|
||||||
|
|
||||||
|
* Add support for IPv6 proxies
|
||||||
|
* Shared configuration implementation for easier maintained code
|
||||||
|
* Use Gson for json parsing, because it's supported on all platforms and removes code duplicates
|
||||||
|
* Clean up project code
|
||||||
* Drop support for deprecated AuthMe API
|
* Drop support for deprecated AuthMe API
|
||||||
* Remove legacy database migration code
|
* Remove legacy database migration code
|
||||||
* Drop support for RoyalAuth, because it doesn't seem to be supported anymore
|
* Drop support for RoyalAuth, because it doesn't seem to be supported anymore
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.github.games647.fastlogin.bukkit;
|
package com.github.games647.fastlogin.bukkit;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.CommonUtil;
|
|
||||||
import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
|
import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
|
||||||
import com.github.games647.fastlogin.core.mojang.SkinProperties;
|
import com.github.games647.fastlogin.core.mojang.SkinProperties;
|
||||||
import com.github.games647.fastlogin.core.mojang.VerificationReply;
|
import com.github.games647.fastlogin.core.mojang.VerificationReply;
|
||||||
@ -44,9 +43,7 @@ public class MojangApiBukkit extends MojangApiConnector {
|
|||||||
//validate parsing
|
//validate parsing
|
||||||
//http://wiki.vg/Protocol_Encryption#Server
|
//http://wiki.vg/Protocol_Encryption#Server
|
||||||
VerificationReply verification = gson.fromJson(reader, VerificationReply.class);
|
VerificationReply verification = gson.fromJson(reader, VerificationReply.class);
|
||||||
|
playerSession.setUuid(verification.getId());
|
||||||
String uuid = verification.getId();
|
|
||||||
playerSession.setUuid(CommonUtil.parseId(uuid));
|
|
||||||
|
|
||||||
SkinProperties[] properties = verification.getProperties();
|
SkinProperties[] properties = verification.getProperties();
|
||||||
if (properties != null && properties.length > 0) {
|
if (properties != null && properties.length > 0) {
|
||||||
|
@ -77,7 +77,7 @@ public class ProtocolLibListener extends PacketAdapter {
|
|||||||
PacketContainer packet = packetEvent.getPacket();
|
PacketContainer packet = packetEvent.getPacket();
|
||||||
|
|
||||||
String username = packet.getGameProfiles().read(0).getName();
|
String username = packet.getGameProfiles().read(0).getName();
|
||||||
plugin.getLogger().log(Level.FINER, "Player {0} with {1} connecting", new Object[]{sessionKey, username});
|
plugin.getLogger().log(Level.FINER, "GameProfile {0} with {1} connecting", new Object[]{sessionKey, username});
|
||||||
|
|
||||||
packetEvent.getAsyncMarker().incrementProcessingDelay();
|
packetEvent.getAsyncMarker().incrementProcessingDelay();
|
||||||
Runnable nameCheckTask = new NameCheckTask(plugin, packetEvent, random, player, username);
|
Runnable nameCheckTask = new NameCheckTask(plugin, packetEvent, random, player, username);
|
||||||
|
@ -52,7 +52,7 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
BukkitLoginSession session = plugin.getLoginSessions().get(player.getAddress().toString());
|
BukkitLoginSession session = plugin.getLoginSessions().get(player.getAddress().toString());
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
disconnect(plugin.getCore().getMessage("invalid-request"), true
|
disconnect(plugin.getCore().getMessage("invalid-request"), true
|
||||||
, "Player {0} tried to send encryption response at invalid state", player.getAddress());
|
, "GameProfile {0} tried to send encryption response at invalid state", player.getAddress());
|
||||||
} else {
|
} else {
|
||||||
verifyResponse(session);
|
verifyResponse(session);
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
|
|
||||||
String username = session.getUsername();
|
String username = session.getUsername();
|
||||||
if (plugin.getCore().getApiConnector().hasJoinedServer(session, serverId, player.getAddress())) {
|
if (plugin.getCore().getApiConnector().hasJoinedServer(session, serverId, player.getAddress())) {
|
||||||
plugin.getLogger().log(Level.INFO, "Player {0} has a verified premium account", username);
|
plugin.getLogger().log(Level.INFO, "GameProfile {0} has a verified premium account", username);
|
||||||
|
|
||||||
session.setVerified(true);
|
session.setVerified(true);
|
||||||
setPremiumUUID(session.getUuid());
|
setPremiumUUID(session.getUuid());
|
||||||
@ -105,7 +105,7 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
} else {
|
} else {
|
||||||
//user tried to fake a authentication
|
//user tried to fake a authentication
|
||||||
disconnect(plugin.getCore().getMessage("invalid-session"), true
|
disconnect(plugin.getCore().getMessage("invalid-session"), true
|
||||||
, "Player {0} ({1}) tried to log in with an invalid session ServerId: {2}"
|
, "GameProfile {0} ({1}) tried to log in with an invalid session ServerId: {2}"
|
||||||
, session.getUsername(), player.getAddress(), serverId);
|
, session.getUsername(), player.getAddress(), serverId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ public class VerifyResponseTask implements Runnable {
|
|||||||
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(cipher, privateKey, responseVerify))) {
|
if (!Arrays.equals(requestVerify, EncryptionUtil.decrypt(cipher, privateKey, responseVerify))) {
|
||||||
//check if the verify token are equal to the server sent one
|
//check if the verify token are equal to the server sent one
|
||||||
disconnect(plugin.getCore().getMessage("invalid-verify-token"), true
|
disconnect(plugin.getCore().getMessage("invalid-verify-token"), true
|
||||||
, "Player {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}"
|
, "GameProfile {0} ({1}) tried to login with an invalid verify token. Server: {2} Client: {3}"
|
||||||
, session.getUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
|
, session.getUsername(), packetEvent.getPlayer().getAddress(), requestVerify, responseVerify);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package com.github.games647.fastlogin.core.hooks;
|
|||||||
/**
|
/**
|
||||||
* Represents a supporting authentication plugin in BungeeCord and Bukkit/Spigot/... servers
|
* Represents a supporting authentication plugin in BungeeCord and Bukkit/Spigot/... servers
|
||||||
*
|
*
|
||||||
* @param <P> either org.bukkit.entity.Player for Bukkit or net.md_5.bungee.api.connection.ProxiedPlayer for BungeeCord
|
* @param <P> either org.bukkit.entity.GameProfile for Bukkit or net.md_5.bungee.api.connection.ProxiedPlayer for BungeeCord
|
||||||
*/
|
*/
|
||||||
public interface AuthPlugin<P> {
|
public interface AuthPlugin<P> {
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package com.github.games647.fastlogin.core.mojang;
|
package com.github.games647.fastlogin.core.mojang;
|
||||||
|
|
||||||
public class Player {
|
import java.util.UUID;
|
||||||
|
|
||||||
private String id;
|
public class GameProfile {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
public String getId() {
|
public UUID getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -53,7 +54,7 @@ public class MojangApiConnector {
|
|||||||
private final int rateLimit;
|
private final int rateLimit;
|
||||||
private long lastRateLimit;
|
private long lastRateLimit;
|
||||||
|
|
||||||
protected final Gson gson = new Gson();
|
protected final Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create();
|
||||||
protected final Logger logger;
|
protected final Logger logger;
|
||||||
|
|
||||||
public MojangApiConnector(Logger logger, Collection<String> localAddresses, int rateLimit
|
public MojangApiConnector(Logger logger, Collection<String> localAddresses, int rateLimit
|
||||||
@ -122,15 +123,14 @@ public class MojangApiConnector {
|
|||||||
private UUID getUUIDFromJson(String json) {
|
private UUID getUUIDFromJson(String json) {
|
||||||
boolean isArray = json.startsWith("[");
|
boolean isArray = json.startsWith("[");
|
||||||
|
|
||||||
Player mojangPlayer;
|
GameProfile mojangPlayer;
|
||||||
if (isArray) {
|
if (isArray) {
|
||||||
mojangPlayer = gson.fromJson(json, Player[].class)[0];
|
mojangPlayer = gson.fromJson(json, GameProfile[].class)[0];
|
||||||
} else {
|
} else {
|
||||||
mojangPlayer = gson.fromJson(json, Player.class);
|
mojangPlayer = gson.fromJson(json, GameProfile.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
String id = mojangPlayer.getId();
|
return mojangPlayer.getId();
|
||||||
return CommonUtil.parseId(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HttpsURLConnection getConnection(String url, Proxy proxy) throws IOException {
|
protected HttpsURLConnection getConnection(String url, Proxy proxy) throws IOException {
|
||||||
@ -141,11 +141,9 @@ public class MojangApiConnector {
|
|||||||
connection.setRequestProperty("Content-Type", "application/json");
|
connection.setRequestProperty("Content-Type", "application/json");
|
||||||
connection.setRequestProperty("User-Agent", USER_AGENT);
|
connection.setRequestProperty("User-Agent", USER_AGENT);
|
||||||
|
|
||||||
//this connection doesn't need to be closed. So can make use of keep alive in java
|
connection.setSSLSocketFactory(sslFactory);
|
||||||
if (sslFactory != null) {
|
|
||||||
connection.setSSLSocketFactory(sslFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//this connection doesn't need to be closed. So can make use of keep alive in java
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,11 @@ package com.github.games647.fastlogin.core.mojang;
|
|||||||
|
|
||||||
public class SkinProperties {
|
public class SkinProperties {
|
||||||
|
|
||||||
private String name;
|
|
||||||
private String value;
|
private String value;
|
||||||
private String signature;
|
private String signature;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return "textures";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue() {
|
public String getValue() {
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.github.games647.fastlogin.core.mojang;
|
||||||
|
|
||||||
|
import com.github.games647.fastlogin.core.CommonUtil;
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UUIDTypeAdapter extends TypeAdapter<UUID> {
|
||||||
|
|
||||||
|
public void write(JsonWriter out, UUID value) throws IOException {
|
||||||
|
out.value(fromUUID(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID read(JsonReader in) throws IOException {
|
||||||
|
return fromString(in.nextString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fromUUID(UUID value) {
|
||||||
|
return value.toString().replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID fromString(String input) {
|
||||||
|
return CommonUtil.parseId(input);
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,14 @@
|
|||||||
package com.github.games647.fastlogin.core.mojang;
|
package com.github.games647.fastlogin.core.mojang;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class VerificationReply {
|
public class VerificationReply {
|
||||||
|
|
||||||
private String id;
|
private UUID id;
|
||||||
private String name;
|
private String name;
|
||||||
private SkinProperties[] properties;
|
private SkinProperties[] properties;
|
||||||
|
|
||||||
public String getId() {
|
public UUID getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import net.md_5.bungee.config.ConfigurationProvider;
|
|||||||
import net.md_5.bungee.config.YamlConfiguration;
|
import net.md_5.bungee.config.YamlConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param <P> Player class
|
* @param <P> GameProfile class
|
||||||
* @param <C> CommandSender
|
* @param <C> CommandSender
|
||||||
* @param <T> Plugin class
|
* @param <T> Plugin class
|
||||||
*/
|
*/
|
||||||
|
@ -65,7 +65,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkPremiumName(S source, String username, PlayerProfile profile) throws Exception {
|
private boolean checkPremiumName(S source, String username, PlayerProfile profile) throws Exception {
|
||||||
core.getPlugin().getLogger().log(Level.FINER, "Player {0} uses a premium username", username);
|
core.getPlugin().getLogger().log(Level.FINER, "GameProfile {0} uses a premium username", username);
|
||||||
if (core.getConfig().get("autoRegister", false) && (authHook == null || !authHook.isRegistered(username))) {
|
if (core.getConfig().get("autoRegister", false) && (authHook == null || !authHook.isRegistered(username))) {
|
||||||
requestPremiumLogin(source, profile, username, false);
|
requestPremiumLogin(source, profile, username, false);
|
||||||
return true;
|
return true;
|
||||||
@ -80,7 +80,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
|||||||
PlayerProfile profile = core.getStorage().loadProfile(premiumUUID);
|
PlayerProfile profile = core.getStorage().loadProfile(premiumUUID);
|
||||||
if (profile != null) {
|
if (profile != null) {
|
||||||
//uuid exists in the database
|
//uuid exists in the database
|
||||||
core.getPlugin().getLogger().log(Level.FINER, "Player {0} changed it's username", premiumUUID);
|
core.getPlugin().getLogger().log(Level.FINER, "GameProfile {0} changed it's username", premiumUUID);
|
||||||
|
|
||||||
//update the username to the new one in the database
|
//update the username to the new one in the database
|
||||||
profile.setPlayerName(username);
|
profile.setPlayerName(username);
|
||||||
|
@ -62,7 +62,7 @@ premiumUuid: false
|
|||||||
# #### Case 1
|
# #### Case 1
|
||||||
# nameChangeCheck = false ----- autoRegister = false
|
# nameChangeCheck = false ----- autoRegister = false
|
||||||
#
|
#
|
||||||
# Player logins as cracked until the player invoked the command /premium. Then we could override the existing database
|
# GameProfile logins as cracked until the player invoked the command /premium. Then we could override the existing database
|
||||||
# record.
|
# record.
|
||||||
#
|
#
|
||||||
# #### Case 2
|
# #### Case 2
|
||||||
|
@ -24,25 +24,25 @@
|
|||||||
# Switch mode is activated and a new (non-whitelist) cracked player tries to join
|
# Switch mode is activated and a new (non-whitelist) cracked player tries to join
|
||||||
switch-kick-message: '&4Only paid minecraft whitelisted accounts are allowed to join this server'
|
switch-kick-message: '&4Only paid minecraft whitelisted accounts are allowed to join this server'
|
||||||
|
|
||||||
# Player activated premium login in order to skip offline authentication
|
# GameProfile activated premium login in order to skip offline authentication
|
||||||
add-premium: '&2Added to the list of premium players'
|
add-premium: '&2Added to the list of premium players'
|
||||||
|
|
||||||
# Player activated premium login in order to skip offline authentication
|
# GameProfile activated premium login in order to skip offline authentication
|
||||||
add-premium-other: '&2Player has been added to the premium list'
|
add-premium-other: '&2Player has been added to the premium list'
|
||||||
|
|
||||||
# Player is already set be a paid account
|
# GameProfile is already set be a paid account
|
||||||
already-exists: '&4You are already on the premium list'
|
already-exists: '&4You are already on the premium list'
|
||||||
|
|
||||||
# Player is already set be a paid account
|
# GameProfile is already set be a paid account
|
||||||
already-exists-other: '&4Player is already on the premium list'
|
already-exists-other: '&4Player is already on the premium list'
|
||||||
|
|
||||||
# Player was changed to be cracked
|
# GameProfile was changed to be cracked
|
||||||
remove-premium: '&2Removed from the list of premium players'
|
remove-premium: '&2Removed from the list of premium players'
|
||||||
|
|
||||||
# Player is already set to be cracked
|
# GameProfile is already set to be cracked
|
||||||
not-premium: '&4You are not in the premium list'
|
not-premium: '&4You are not in the premium list'
|
||||||
|
|
||||||
# Player is already set to be cracked
|
# GameProfile is already set to be cracked
|
||||||
not-premium-other: '&4Player is not in the premium list'
|
not-premium-other: '&4Player is not in the premium list'
|
||||||
|
|
||||||
# Admin wanted to change the premium of a user that isn't known to the plugin
|
# Admin wanted to change the premium of a user that isn't known to the plugin
|
||||||
@ -58,7 +58,7 @@ auto-login: '&2Auto logged in'
|
|||||||
auto-register: '&2Auto registered with password: %password
|
auto-register: '&2Auto registered with password: %password
|
||||||
You may want change it?'
|
You may want change it?'
|
||||||
|
|
||||||
# Player is not able to toggle the premium state of other players
|
# GameProfile is not able to toggle the premium state of other players
|
||||||
no-permission: '&4Not enough permissions'
|
no-permission: '&4Not enough permissions'
|
||||||
|
|
||||||
# Although the console can toggle the premium state, it's not possible for the console itself.
|
# Although the console can toggle the premium state, it's not possible for the console itself.
|
||||||
|
Reference in New Issue
Block a user