Force login only if the save process was successful

This commit is contained in:
games647
2016-05-03 15:58:22 +02:00
parent 6edd40742d
commit dfe37dfc1b
8 changed files with 182 additions and 133 deletions

View File

@ -0,0 +1,80 @@
package com.github.games647.fastlogin.bukkit;
import com.github.games647.fastlogin.bukkit.hooks.BukkitAuthPlugin;
import java.util.logging.Level;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue;
public class ForceLoginTask implements Runnable {
private final FastLoginBukkit plugin;
private final Player player;
public ForceLoginTask(FastLoginBukkit plugin, Player player) {
this.plugin = plugin;
this.player = player;
}
@Override
public void run() {
if (!player.isOnline()) {
return;
}
//remove the bungeecord identifier
String id = '/' + player.getAddress().getAddress().getHostAddress() + ':' + player.getAddress().getPort();
PlayerSession session = plugin.getSessions().get(id);
//blacklist this target player for BungeeCord Id brute force attacks
player.setMetadata(plugin.getName(), new FixedMetadataValue(plugin, true));
//check if it's the same player as we checked before
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();
if (session == null || !player.getName().equals(session.getUsername()) || authPlugin == null) {
return;
}
Storage storage = plugin.getStorage();
PlayerProfile playerProfile = null;
if (storage != null) {
playerProfile = storage.getProfile(session.getUsername(), false);
}
if (session.isVerified()) {
boolean success = true;
if (playerProfile != null) {
playerProfile.setUuid(session.getUuid());
playerProfile.setPremium(true);
success = storage.save(playerProfile);
}
if (success) {
if (session.needsRegistration()) {
forceRegister(authPlugin, player);
} else {
forceLogin(authPlugin, player);
}
}
} else if (playerProfile != null) {
storage.save(playerProfile);
}
}
private void forceRegister(BukkitAuthPlugin authPlugin, Player player) {
plugin.getLogger().log(Level.FINE, "Register player {0}", player.getName());
String generatedPassword = plugin.generateStringPassword();
authPlugin.forceRegister(player, generatedPassword);
player.sendMessage(ChatColor.DARK_GREEN + "Auto registered with password: " + generatedPassword);
player.sendMessage(ChatColor.DARK_GREEN + "You may want change it?");
}
private void forceLogin(BukkitAuthPlugin authPlugin, Player player) {
plugin.getLogger().log(Level.FINE, "Logging player {0} in", player.getName());
authPlugin.forceLogin(player);
player.sendMessage(ChatColor.DARK_GREEN + "Auto logged in");
}
}

View File

@ -3,21 +3,15 @@ package com.github.games647.fastlogin.bukkit.listener;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.PlayerProfile;
import com.github.games647.fastlogin.bukkit.ForceLoginTask;
import com.github.games647.fastlogin.bukkit.PlayerSession;
import com.github.games647.fastlogin.bukkit.Storage;
import com.github.games647.fastlogin.bukkit.hooks.BukkitAuthPlugin;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.metadata.FixedMetadataValue;
/**
* This listener tells authentication plugins if the player has a premium account and we checked it successfully. So the
@ -47,70 +41,8 @@ public class BukkitJoinListener implements Listener {
}
}
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
if (!player.isOnline()) {
return;
}
//remove the bungeecord identifier
String id = '/' + player.getAddress().getAddress().getHostAddress() + ':'
+ player.getAddress().getPort();
PlayerSession session = plugin.getSessions().get(id);
//blacklist this target player for BungeeCord Id brute force attacks
player.setMetadata(plugin.getName(), new FixedMetadataValue(plugin, true));
//check if it's the same player as we checked before
if (session != null && player.getName().equals(session.getUsername())) {
final Storage storage = plugin.getStorage();
PlayerProfile playerProfile = null;
if (storage != null) {
playerProfile = storage.getProfile(session.getUsername(), false);
}
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();
if (session.isVerified() && authPlugin != null) {
if (session.needsRegistration()) {
plugin.getLogger().log(Level.FINE, "Register player {0}", player.getName());
String generatedPassword = plugin.generateStringPassword();
authPlugin.forceRegister(player, generatedPassword);
player.sendMessage(ChatColor.DARK_GREEN + "Auto registered with password: "
+ generatedPassword);
player.sendMessage(ChatColor.DARK_GREEN + "You may want change it?");
if (playerProfile != null) {
playerProfile.setUuid(session.getUuid());
playerProfile.setPremium(true);
}
} else {
plugin.getLogger().log(Level.FINE, "Logging player {0} in", player.getName());
authPlugin.forceLogin(player);
player.sendMessage(ChatColor.DARK_GREEN + "Auto logged in");
if (playerProfile != null) {
playerProfile.setUuid(session.getUuid());
playerProfile.setPremium(true);
}
}
}
final PlayerProfile toSave = playerProfile;
if (toSave != null) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
storage.save(toSave);
}
});
}
}
}
//Wait before auth plugin and we received a message from BungeeCord initializes the player
}, DELAY_LOGIN);
//Wait before auth plugin and we received a message from BungeeCord initializes the player
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, new ForceLoginTask(plugin, player), DELAY_LOGIN);
}
@EventHandler

View File

@ -37,7 +37,9 @@ public class ProtocolSupportListener implements Listener {
PlayerProfile playerProfile = plugin.getStorage().getProfile(username, true);
if (playerProfile != null) {
if (playerProfile.isPremium()) {
startPremiumSession(username, loginStartEvent, true);
if (playerProfile.getUserId() != -1) {
startPremiumSession(username, loginStartEvent, true);
}
} else if (playerProfile.getUserId() == -1) {
//user not exists in the db
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();

View File

@ -78,7 +78,9 @@ public class StartPacketListener extends PacketAdapter {
PlayerProfile playerProfile = plugin.getStorage().getProfile(username, true);
if (playerProfile != null) {
if (playerProfile.isPremium()) {
enablePremiumLogin(username, sessionKey, player, packetEvent, true);
if (playerProfile.getUserId() != -1) {
enablePremiumLogin(username, sessionKey, player, packetEvent, true);
}
} else if (playerProfile.getUserId() == -1) {
//user not exists in the db
BukkitAuthPlugin authPlugin = plugin.getAuthPlugin();

View File

@ -2,6 +2,7 @@ package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthHook;
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthPlugin;
import com.google.common.cache.CacheBuilder;
import java.io.File;
import java.io.IOException;
@ -9,7 +10,10 @@ import java.io.InputStream;
import java.nio.file.Files;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.config.Configuration;
@ -39,6 +43,11 @@ public class FastLoginBungee extends Plugin {
private final Random random = new Random();
private final ConcurrentMap<PendingConnection, Object> pendingAutoRegister = CacheBuilder
.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.<PendingConnection, Object>build().asMap();
@Override
public void onEnable() {
if (!getDataFolder().exists()) {
@ -114,6 +123,10 @@ public class FastLoginBungee extends Plugin {
return mojangApiConnector;
}
public ConcurrentMap<PendingConnection, Object> getPendingAutoRegister() {
return pendingAutoRegister;
}
/**
* Get the auth plugin hook for BungeeCord
*

View File

@ -0,0 +1,71 @@
package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthPlugin;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import java.util.UUID;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
public class ForceLoginTask implements Runnable {
private final FastLoginBungee plugin;
private final ProxiedPlayer player;
public ForceLoginTask(FastLoginBungee plugin, ProxiedPlayer player) {
this.plugin = plugin;
this.player = player;
}
@Override
public void run() {
PlayerProfile playerProfile = plugin.getStorage().getProfile(player.getName(), false);
boolean success = true;
if (playerProfile.getUserId() == -1) {
playerProfile.setPremium(player.getPendingConnection().isOnlineMode());
if (player.getPendingConnection().isOnlineMode()) {
playerProfile.setUuid(player.getUniqueId());
}
success = plugin.getStorage().save(playerProfile);
}
//force login only on success
if (success && player.getPendingConnection().isOnlineMode()) {
Server server = player.getServer();
boolean autoRegister = plugin.getPendingAutoRegister().remove(player.getPendingConnection()) != null;
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
//subchannel name
if (autoRegister) {
dataOutput.writeUTF("AUTO_REGISTER");
} else {
dataOutput.writeUTF("AUTO_LOGIN");
}
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
dataOutput.writeUTF(player.getName());
//proxy identifier to check if it's a acceptable proxy
UUID proxyId = UUID.fromString(plugin.getProxy().getConfig().getUuid());
dataOutput.writeLong(proxyId.getMostSignificantBits());
dataOutput.writeLong(proxyId.getLeastSignificantBits());
server.sendData(plugin.getDescription().getName(), dataOutput.toByteArray());
BungeeAuthPlugin authPlugin = plugin.getBungeeAuthPlugin();
if (authPlugin != null) {
if (autoRegister) {
String password = plugin.generateStringPassword();
authPlugin.forceRegister(player, password);
} else {
authPlugin.forceLogin(player);
}
}
}
}
}

View File

@ -1,14 +1,10 @@
package com.github.games647.fastlogin.bungee;
import com.github.games647.fastlogin.bungee.hooks.BungeeAuthPlugin;
import com.google.common.cache.CacheBuilder;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import net.md_5.bungee.api.ChatColor;
@ -31,10 +27,6 @@ import net.md_5.bungee.event.EventHandler;
public class PlayerConnectionListener implements Listener {
protected final FastLoginBungee plugin;
private final ConcurrentMap<PendingConnection, Object> pendingAutoRegister = CacheBuilder
.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.<PendingConnection, Object>build().asMap();
public PlayerConnectionListener(FastLoginBungee plugin) {
this.plugin = plugin;
@ -53,7 +45,9 @@ public class PlayerConnectionListener implements Listener {
PlayerProfile playerProfile = plugin.getStorage().getProfile(username, true);
if (playerProfile != null) {
if (playerProfile.isPremium()) {
connection.setOnlineMode(true);
if (playerProfile.getUserId() != -1) {
connection.setOnlineMode(true);
}
} else if (playerProfile.getUserId() == -1) {
//user not exists in the db
BungeeAuthPlugin authPlugin = plugin.getBungeeAuthPlugin();
@ -63,7 +57,7 @@ public class PlayerConnectionListener implements Listener {
if (premiumUUID != null) {
plugin.getLogger().log(Level.FINER, "Player {0} uses a premium username", username);
connection.setOnlineMode(true);
pendingAutoRegister.put(connection, new Object());
plugin.getPendingAutoRegister().put(connection, new Object());
}
}
}
@ -73,51 +67,7 @@ public class PlayerConnectionListener implements Listener {
@EventHandler
public void onServerConnected(ServerConnectedEvent serverConnectedEvent) {
ProxiedPlayer player = serverConnectedEvent.getPlayer();
//send message even when the online mode is activated by default
final PlayerProfile playerProfile = plugin.getStorage().getProfile(player.getName(), false);
if (playerProfile.getUserId() == -1) {
ProxyServer.getInstance().getScheduler().runAsync(plugin, new Runnable() {
@Override
public void run() {
plugin.getStorage().save(playerProfile);
}
});
}
if (player.getPendingConnection().isOnlineMode()) {
Server server = serverConnectedEvent.getServer();
boolean autoRegister = pendingAutoRegister.remove(player.getPendingConnection()) != null;
ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput();
//subchannel name
if (autoRegister) {
dataOutput.writeUTF("AUTO_REGISTER");
} else {
dataOutput.writeUTF("AUTO_LOGIN");
}
//Data is sent through a random player. We have to tell the Bukkit version of this plugin the target
dataOutput.writeUTF(player.getName());
//proxy identifier to check if it's a acceptable proxy
UUID proxyId = UUID.fromString(plugin.getProxy().getConfig().getUuid());
dataOutput.writeLong(proxyId.getMostSignificantBits());
dataOutput.writeLong(proxyId.getLeastSignificantBits());
server.sendData(plugin.getDescription().getName(), dataOutput.toByteArray());
BungeeAuthPlugin authPlugin = plugin.getBungeeAuthPlugin();
if (authPlugin != null) {
if (autoRegister) {
String password = plugin.generateStringPassword();
authPlugin.forceRegister(player, password);
} else {
authPlugin.forceLogin(player);
}
}
}
ProxyServer.getInstance().getScheduler().runAsync(plugin, new ForceLoginTask(plugin, player));
}
@EventHandler
@ -136,9 +86,9 @@ public class PlayerConnectionListener implements Listener {
byte[] data = pluginMessageEvent.getData();
ByteArrayDataInput dataInput = ByteStreams.newDataInput(data);
String subchannel = dataInput.readUTF();
if ("ON".equals(subchannel)) {
final ProxiedPlayer forPlayer = (ProxiedPlayer) pluginMessageEvent.getReceiver();
final ProxiedPlayer forPlayer = (ProxiedPlayer) pluginMessageEvent.getReceiver();
if ("ON".equals(subchannel)) {
ProxyServer.getInstance().getScheduler().runAsync(plugin, new Runnable() {
@Override
public void run() {
@ -159,7 +109,6 @@ public class PlayerConnectionListener implements Listener {
}
});
} else if ("OFF".equals(subchannel)) {
final ProxiedPlayer forPlayer = (ProxiedPlayer) pluginMessageEvent.getReceiver();
ProxyServer.getInstance().getScheduler().runAsync(plugin, new Runnable() {
@Override
public void run() {

View File

@ -4,7 +4,7 @@
<groupId>com.github.games647</groupId>
<!--This have to be in lowercase because it's used by plugin.yml-->
<artifactId>fastlogin-parent</artifactId>
<artifactId>fastlogin</artifactId>
<packaging>pom</packaging>
<name>FastLogin</name>
@ -89,7 +89,7 @@
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.4.5</version>
<version>2.4.6</version>
</dependency>
<!--Logging framework implements slf4j which is required by hikari-->