mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-07-30 02:37:34 +02:00
Use Instant for timestamps
This commit is contained in:
4
.github/ISSUE_TEMPLATE.md
vendored
4
.github/ISSUE_TEMPLATE.md
vendored
@ -13,9 +13,9 @@ The actions that cause the issue
|
|||||||
This can be found by running `/pl`
|
This can be found by running `/pl`
|
||||||
|
|
||||||
### Environment description
|
### Environment description
|
||||||
Standalone server/Bungeecord network, SQLite/MySql, ...
|
Standalone server/Bungeecord network, SQLite/MySQL, ...
|
||||||
|
|
||||||
### Plugin version:
|
### Plugin version or build number (don't write latest):
|
||||||
This can be found by running `/version plugin-name`
|
This can be found by running `/version plugin-name`
|
||||||
|
|
||||||
### Error Log:
|
### Error Log:
|
||||||
|
@ -37,7 +37,8 @@ So they don't need to enter passwords. This is also called auto login (auto-logi
|
|||||||
* fastlogin.command.import
|
* fastlogin.command.import
|
||||||
|
|
||||||
### Requirements:
|
### Requirements:
|
||||||
* Plugin: [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or [ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
|
* Plugin: [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or
|
||||||
|
[ProtocolSupport](https://www.spigotmc.org/resources/protocolsupport.7201/)
|
||||||
* [Spigot](https://www.spigotmc.org) 1.7+
|
* [Spigot](https://www.spigotmc.org) 1.7+
|
||||||
* Java 8+
|
* Java 8+
|
||||||
* Run Spigot and/or BungeeCord/Waterfall in offline mode (see server.properties or config.yml)
|
* Run Spigot and/or BungeeCord/Waterfall in offline mode (see server.properties or config.yml)
|
||||||
@ -77,5 +78,6 @@ Put your stats id from the BungeeCord config into this file
|
|||||||
5. Download and Install FastLogin on BungeeCord AND Spigot
|
5. Download and Install FastLogin on BungeeCord AND Spigot
|
||||||
6. Check your database settings in the config of FastLogin on BungeeCord
|
6. Check your database settings in the config of FastLogin on BungeeCord
|
||||||
7. Set your proxy (BungeeCord) in offline mode by setting the value onlinemode in your config.yml to false
|
7. Set your proxy (BungeeCord) in offline mode by setting the value onlinemode in your config.yml to false
|
||||||
8. You should *always* firewall your spigot server that it's only accessible through BungeeCord https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
|
8. You should *always* firewall your Spigot server that it's only accessible through BungeeCord
|
||||||
|
https://www.spigotmc.org/wiki/bungeecord-installation/#post-installation
|
||||||
9. (BungeeCord doesn't support SQLite per default, so you should change the configuration to MySQL or MariaDB)
|
9. (BungeeCord doesn't support SQLite per default, so you should change the configuration to MySQL or MariaDB)
|
||||||
|
@ -2,8 +2,8 @@ package com.github.games647.fastlogin.bukkit;
|
|||||||
|
|
||||||
import com.github.games647.fastlogin.bukkit.commands.CrackedCommand;
|
import com.github.games647.fastlogin.bukkit.commands.CrackedCommand;
|
||||||
import com.github.games647.fastlogin.bukkit.commands.PremiumCommand;
|
import com.github.games647.fastlogin.bukkit.commands.PremiumCommand;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.JoinListener;
|
|
||||||
import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
|
import com.github.games647.fastlogin.bukkit.listener.BungeeListener;
|
||||||
|
import com.github.games647.fastlogin.bukkit.listener.JoinListener;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.LoginSkinApplyListener;
|
import com.github.games647.fastlogin.bukkit.listener.protocollib.LoginSkinApplyListener;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
|
import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener;
|
||||||
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
|
import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener;
|
||||||
@ -17,11 +17,11 @@ import com.google.common.io.ByteArrayDataOutput;
|
|||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -188,6 +188,11 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
sender.sendPluginMessage(this, getName(), dataOutput.toByteArray());
|
sender.sendPluginMessage(this, getName(), dataOutput.toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path getPluginFolder() {
|
||||||
|
return getDataFolder().toPath();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Logger getLog() {
|
public Logger getLog() {
|
||||||
return logger;
|
return logger;
|
||||||
@ -206,6 +211,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MojangApiConnector makeApiConnector(List<String> addresses, int requests, List<HostAndPort> proxies) {
|
public MojangApiConnector makeApiConnector(List<String> addresses, int requests, List<HostAndPort> proxies) {
|
||||||
return new MojangApiBukkit(getLog(), addresses, requests, proxies);
|
return new MojangApiBukkit(logger, addresses, requests, proxies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import java.net.HttpURLConnection;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ public class MojangApiBukkit extends MojangApiConnector {
|
|||||||
"username=%s&serverId=%s&ip=%s";
|
"username=%s&serverId=%s&ip=%s";
|
||||||
|
|
||||||
public MojangApiBukkit(Logger logger, Collection<String> localAddresses, int rateLimit
|
public MojangApiBukkit(Logger logger, Collection<String> localAddresses, int rateLimit
|
||||||
, List<HostAndPort> proxies) {
|
, Iterable<HostAndPort> proxies) {
|
||||||
super(logger, localAddresses, rateLimit, proxies);
|
super(logger, localAddresses, rateLimit, proxies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,9 +93,7 @@ public class CrazyLoginHook implements AuthPlugin<Player> {
|
|||||||
//create a fake account - this will be saved to the database with the password=FAILEDLOADING
|
//create a fake account - this will be saved to the database with the password=FAILEDLOADING
|
||||||
//user cannot login with that password unless the admin uses plain text
|
//user cannot login with that password unless the admin uses plain text
|
||||||
//this automatically marks the player as logged in
|
//this automatically marks the player as logged in
|
||||||
playerData = new LoginPlayerData(player);
|
crazyDatabase.save(new LoginPlayerData(player));
|
||||||
crazyDatabase.save(playerData);
|
|
||||||
|
|
||||||
return forceLogin(player);
|
return forceLogin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,9 @@ import io.github.lucaseasedup.logit.CancelledState;
|
|||||||
import io.github.lucaseasedup.logit.LogItCore;
|
import io.github.lucaseasedup.logit.LogItCore;
|
||||||
import io.github.lucaseasedup.logit.account.Account;
|
import io.github.lucaseasedup.logit.account.Account;
|
||||||
import io.github.lucaseasedup.logit.session.SessionManager;
|
import io.github.lucaseasedup.logit.session.SessionManager;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,7 +25,6 @@ public class LogItHook implements AuthPlugin<Player> {
|
|||||||
SessionManager sessionManager = LogItCore.getInstance().getSessionManager();
|
SessionManager sessionManager = LogItCore.getInstance().getSessionManager();
|
||||||
return sessionManager.isSessionAlive(player)
|
return sessionManager.isSessionAlive(player)
|
||||||
|| sessionManager.startSession(player) == CancelledState.NOT_CANCELLED;
|
|| sessionManager.startSession(player) == CancelledState.NOT_CANCELLED;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -34,8 +36,10 @@ public class LogItHook implements AuthPlugin<Player> {
|
|||||||
public boolean forceRegister(Player player, String password) {
|
public boolean forceRegister(Player player, String password) {
|
||||||
Account account = new Account(player.getName());
|
Account account = new Account(player.getName());
|
||||||
account.changePassword(password);
|
account.changePassword(password);
|
||||||
account.setLastActiveDate(System.currentTimeMillis() / 1000);
|
|
||||||
account.setRegistrationDate(System.currentTimeMillis() / 1000);
|
Instant now = Instant.now();
|
||||||
|
account.setLastActiveDate(now.getEpochSecond());
|
||||||
|
account.setRegistrationDate(now.getEpochSecond());
|
||||||
return LogItCore.getInstance().getAccountManager().insertAccount(account) == CancelledState.NOT_CANCELLED;
|
return LogItCore.getInstance().getAccountManager().insertAccount(account) == CancelledState.NOT_CANCELLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ public class BungeeListener implements PluginMessageListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Set<UUID> loadBungeeCordIds() {
|
public Set<UUID> loadBungeeCordIds() {
|
||||||
Path whitelistFile = plugin.getDataFolder().toPath().resolve(FILE_NAME);
|
Path whitelistFile = plugin.getPluginFolder().resolve(FILE_NAME);
|
||||||
try {
|
try {
|
||||||
if (Files.notExists(whitelistFile)) {
|
if (Files.notExists(whitelistFile)) {
|
||||||
Files.createFile(whitelistFile);
|
Files.createFile(whitelistFile);
|
||||||
|
@ -23,7 +23,8 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
|||||||
private final Player player;
|
private final Player player;
|
||||||
private final String username;
|
private final String username;
|
||||||
|
|
||||||
public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random, Player player, String username) {
|
public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random,
|
||||||
|
Player player, String username) {
|
||||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
|
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
|
||||||
|
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@ -45,7 +46,8 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
|||||||
//minecraft server implementation
|
//minecraft server implementation
|
||||||
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L161
|
//https://github.com/bergerkiller/CraftSource/blob/master/net.minecraft.server/LoginListener.java#L161
|
||||||
@Override
|
@Override
|
||||||
public void requestPremiumLogin(ProtocolLibLoginSource source, PlayerProfile profile, String username, boolean registered) {
|
public void requestPremiumLogin(ProtocolLibLoginSource source, PlayerProfile profile
|
||||||
|
, String username, boolean registered) {
|
||||||
try {
|
try {
|
||||||
source.setOnlineMode();
|
source.setOnlineMode();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -52,13 +52,15 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestPremiumLogin(ProtocolLoginSource source, PlayerProfile profile, String username, boolean registered) {
|
public void requestPremiumLogin(ProtocolLoginSource source, PlayerProfile profile, String username
|
||||||
|
, boolean registered) {
|
||||||
source.setOnlineMode();
|
source.setOnlineMode();
|
||||||
|
|
||||||
String ip = source.getAddress().getAddress().getHostAddress();
|
String ip = source.getAddress().getAddress().getHostAddress();
|
||||||
plugin.getCore().getPendingLogin().put(ip + username, new Object());
|
plugin.getCore().getPendingLogin().put(ip + username, new Object());
|
||||||
|
|
||||||
BukkitLoginSession playerSession = new BukkitLoginSession(username, null, null, registered, profile);
|
BukkitLoginSession playerSession = new BukkitLoginSession(username, null, null
|
||||||
|
, registered, profile);
|
||||||
plugin.getLoginSessions().put(source.getAddress().toString(), playerSession);
|
plugin.getLoginSessions().put(source.getAddress().toString(), playerSession);
|
||||||
if (plugin.getConfig().getBoolean("premiumUuid")) {
|
if (plugin.getConfig().getBoolean("premiumUuid")) {
|
||||||
source.getLoginStartEvent().setUseOnlineModeUUID(true);
|
source.getLoginStartEvent().setUseOnlineModeUUID(true);
|
||||||
|
@ -9,7 +9,9 @@ import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
|||||||
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
import com.github.games647.fastlogin.core.shared.PlatformPlugin;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
@ -79,6 +81,11 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
|||||||
return getDescription().getName();
|
return getDescription().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path getPluginFolder() {
|
||||||
|
return getDataFolder().toPath();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Logger getLog() {
|
public Logger getLog() {
|
||||||
return logger;
|
return logger;
|
||||||
@ -92,11 +99,16 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
|||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public ThreadFactory getThreadFactory() {
|
public ThreadFactory getThreadFactory() {
|
||||||
return new GroupedThreadFactory(this, getName());
|
return new ThreadFactoryBuilder()
|
||||||
|
.setNameFormat(core.getPlugin().getName() + " Database Pool Thread #%1$d")
|
||||||
|
//Hikari create daemons by default
|
||||||
|
.setDaemon(true)
|
||||||
|
.setThreadFactory(new GroupedThreadFactory(this, getName()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MojangApiConnector makeApiConnector(List<String> addresses, int requests, List<HostAndPort> proxies) {
|
public MojangApiConnector makeApiConnector(List<String> addresses, int requests, List<HostAndPort> proxies) {
|
||||||
return new MojangApiConnector(getLog(), addresses, requests, proxies);
|
return new MojangApiConnector(logger, addresses, requests, proxies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import net.md_5.bungee.event.EventPriority;
|
|||||||
public class ConnectListener implements Listener {
|
public class ConnectListener implements Listener {
|
||||||
|
|
||||||
private final FastLoginBungee plugin;
|
private final FastLoginBungee plugin;
|
||||||
|
private final Property[] emptyProperties = {};
|
||||||
|
|
||||||
public ConnectListener(FastLoginBungee plugin) {
|
public ConnectListener(FastLoginBungee plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@ -89,7 +90,7 @@ public class ConnectListener implements Listener {
|
|||||||
//this is null on offline mode
|
//this is null on offline mode
|
||||||
LoginResult loginProfile = initialHandler.getLoginProfile();
|
LoginResult loginProfile = initialHandler.getLoginProfile();
|
||||||
if (loginProfile != null) {
|
if (loginProfile != null) {
|
||||||
loginProfile.setProperties(new Property[]{});
|
loginProfile.setProperties(emptyProperties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,8 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestPremiumLogin(BungeeLoginSource source, PlayerProfile profile, String username, boolean registered) {
|
public void requestPremiumLogin(BungeeLoginSource source, PlayerProfile profile,
|
||||||
|
String username, boolean registered) {
|
||||||
source.setOnlineMode();
|
source.setOnlineMode();
|
||||||
plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile));
|
plugin.getSession().put(source.getConnection(), new BungeeLoginSession(username, registered, profile));
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@ import net.md_5.bungee.api.connection.PendingConnection;
|
|||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.connection.Server;
|
import net.md_5.bungee.api.connection.Server;
|
||||||
|
|
||||||
public class ForceLoginTask extends ForceLoginManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
|
public class ForceLoginTask
|
||||||
|
extends ForceLoginManagement<ProxiedPlayer, CommandSender, BungeeLoginSession, FastLoginBungee> {
|
||||||
|
|
||||||
private final Server server;
|
private final Server server;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.github.games647.fastlogin.core;
|
package com.github.games647.fastlogin.core;
|
||||||
|
|
||||||
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|
||||||
import com.zaxxer.hikari.HikariConfig;
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
|
||||||
@ -10,14 +9,24 @@ import java.sql.PreparedStatement;
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
|
import static java.sql.Statement.RETURN_GENERATED_KEYS;
|
||||||
|
|
||||||
public class AuthStorage {
|
public class AuthStorage {
|
||||||
|
|
||||||
private static final String PREMIUM_TABLE = "premium";
|
private static final String PREMIUM_TABLE = "premium";
|
||||||
|
|
||||||
|
private static final String LOAD_BY_NAME = "SELECT * FROM " + PREMIUM_TABLE + " WHERE Name=? LIMIT 1";
|
||||||
|
private static final String LOAD_BY_UUID = "SELECT * FROM " + PREMIUM_TABLE + " WHERE UUID=? LIMIT 1";
|
||||||
|
private static final String INSERT_PROFILE = "INSERT INTO " + PREMIUM_TABLE + " (UUID, Name, Premium, LastIp) "
|
||||||
|
+ "VALUES (?, ?, ?, ?) ";
|
||||||
|
private static final String UPDATE_PROFILE = "UPDATE " + PREMIUM_TABLE
|
||||||
|
+ " SET UUID=?, Name=?, Premium=?, LastIp=?, LastLogin=CURRENT_TIMESTAMP WHERE UserID=?";
|
||||||
|
|
||||||
private final FastLoginCore<?, ?, ?> core;
|
private final FastLoginCore<?, ?, ?> core;
|
||||||
private final HikariDataSource dataSource;
|
private final HikariDataSource dataSource;
|
||||||
|
|
||||||
@ -38,22 +47,18 @@ public class AuthStorage {
|
|||||||
|
|
||||||
ThreadFactory platformThreadFactory = core.getPlugin().getThreadFactory();
|
ThreadFactory platformThreadFactory = core.getPlugin().getThreadFactory();
|
||||||
if (platformThreadFactory != null) {
|
if (platformThreadFactory != null) {
|
||||||
config.setThreadFactory(new ThreadFactoryBuilder()
|
config.setThreadFactory(platformThreadFactory);
|
||||||
.setNameFormat(core.getPlugin().getName() + " Database Pool Thread #%1$d")
|
|
||||||
//Hikari create daemons by default
|
|
||||||
.setDaemon(true)
|
|
||||||
.setThreadFactory(platformThreadFactory)
|
|
||||||
.build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
databasePath = databasePath.replace("{pluginDir}", core.getPlugin().getDataFolder().getAbsolutePath());
|
String pluginFolder = core.getPlugin().getPluginFolder().toAbsolutePath().toString();
|
||||||
|
databasePath = databasePath.replace("{pluginDir}", pluginFolder);
|
||||||
|
|
||||||
String jdbcUrl = "jdbc:";
|
String jdbcUrl = "jdbc:";
|
||||||
if (driver.contains("sqlite")) {
|
if (driver.contains("sqlite")) {
|
||||||
jdbcUrl += "sqlite" + "://" + databasePath;
|
jdbcUrl += "sqlite://" + databasePath;
|
||||||
config.setConnectionTestQuery("SELECT 1");
|
config.setConnectionTestQuery("SELECT 1");
|
||||||
} else {
|
} else {
|
||||||
jdbcUrl += "mysql" + "://" + host + ':' + port + '/' + databasePath;
|
jdbcUrl += "mysql://" + host + ':' + port + '/' + databasePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
config.setJdbcUrl(jdbcUrl);
|
config.setJdbcUrl(jdbcUrl);
|
||||||
@ -84,8 +89,7 @@ public class AuthStorage {
|
|||||||
|
|
||||||
public PlayerProfile loadProfile(String name) {
|
public PlayerProfile loadProfile(String name) {
|
||||||
try (Connection con = dataSource.getConnection();
|
try (Connection con = dataSource.getConnection();
|
||||||
PreparedStatement loadStmt = con.prepareStatement("SELECT * FROM "
|
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_NAME)) {
|
||||||
+ PREMIUM_TABLE + " WHERE Name=? LIMIT 1")) {
|
|
||||||
loadStmt.setString(1, name);
|
loadStmt.setString(1, name);
|
||||||
|
|
||||||
try (ResultSet resultSet = loadStmt.executeQuery()) {
|
try (ResultSet resultSet = loadStmt.executeQuery()) {
|
||||||
@ -96,7 +100,7 @@ public class AuthStorage {
|
|||||||
|
|
||||||
boolean premium = resultSet.getBoolean(4);
|
boolean premium = resultSet.getBoolean(4);
|
||||||
String lastIp = resultSet.getString(5);
|
String lastIp = resultSet.getString(5);
|
||||||
long lastLogin = resultSet.getTimestamp(6).getTime();
|
Instant lastLogin = resultSet.getTimestamp(6).toInstant();
|
||||||
return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin);
|
return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin);
|
||||||
} else {
|
} else {
|
||||||
return new PlayerProfile(null, name, false, "");
|
return new PlayerProfile(null, name, false, "");
|
||||||
@ -111,8 +115,7 @@ public class AuthStorage {
|
|||||||
|
|
||||||
public PlayerProfile loadProfile(UUID uuid) {
|
public PlayerProfile loadProfile(UUID uuid) {
|
||||||
try (Connection con = dataSource.getConnection();
|
try (Connection con = dataSource.getConnection();
|
||||||
PreparedStatement loadStmt = con.prepareStatement("SELECT * FROM "
|
PreparedStatement loadStmt = con.prepareStatement(LOAD_BY_UUID)) {
|
||||||
+ PREMIUM_TABLE + " WHERE UUID=? LIMIT 1")) {
|
|
||||||
loadStmt.setString(1, uuid.toString().replace("-", ""));
|
loadStmt.setString(1, uuid.toString().replace("-", ""));
|
||||||
|
|
||||||
try (ResultSet resultSet = loadStmt.executeQuery()) {
|
try (ResultSet resultSet = loadStmt.executeQuery()) {
|
||||||
@ -122,7 +125,7 @@ public class AuthStorage {
|
|||||||
String name = resultSet.getString(3);
|
String name = resultSet.getString(3);
|
||||||
boolean premium = resultSet.getBoolean(4);
|
boolean premium = resultSet.getBoolean(4);
|
||||||
String lastIp = resultSet.getString(5);
|
String lastIp = resultSet.getString(5);
|
||||||
long lastLogin = resultSet.getTimestamp(6).getTime();
|
Instant lastLogin = resultSet.getTimestamp(6).toInstant();
|
||||||
return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin);
|
return new PlayerProfile(userId, uuid, name, premium, lastIp, lastLogin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,8 +141,7 @@ public class AuthStorage {
|
|||||||
UUID uuid = playerProfile.getUuid();
|
UUID uuid = playerProfile.getUuid();
|
||||||
|
|
||||||
if (playerProfile.getUserId() == -1) {
|
if (playerProfile.getUserId() == -1) {
|
||||||
try (PreparedStatement saveStmt = con.prepareStatement("INSERT INTO " + PREMIUM_TABLE
|
try (PreparedStatement saveStmt = con.prepareStatement(INSERT_PROFILE, RETURN_GENERATED_KEYS)) {
|
||||||
+ " (UUID, Name, Premium, LastIp) VALUES (?, ?, ?, ?) ", Statement.RETURN_GENERATED_KEYS)) {
|
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
saveStmt.setString(1, null);
|
saveStmt.setString(1, null);
|
||||||
} else {
|
} else {
|
||||||
@ -159,8 +161,7 @@ public class AuthStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try (PreparedStatement saveStmt = con.prepareStatement("UPDATE " + PREMIUM_TABLE
|
try (PreparedStatement saveStmt = con.prepareStatement(UPDATE_PROFILE)) {
|
||||||
+ " SET UUID=?, Name=?, Premium=?, LastIp=?, LastLogin=CURRENT_TIMESTAMP WHERE UserID=?")) {
|
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
saveStmt.setString(1, null);
|
saveStmt.setString(1, null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -136,8 +136,9 @@ public class CompatibleCacheBuilder<K, V> {
|
|||||||
* <p>
|
* <p>
|
||||||
* <p>
|
* <p>
|
||||||
* When {@code size} is zero, elements will be evicted immediately after being loaded into the cache. This has the
|
* When {@code size} is zero, elements will be evicted immediately after being loaded into the cache. This has the
|
||||||
* same effect as invoking {@link #expireAfterWrite expireAfterWrite}{@code (0, unit)} or {@link #expireAfterAccess expireAfterAccess}{@code (0,
|
* same effect as invoking {@link #expireAfterWrite expireAfterWrite}{@code (0, unit)} or
|
||||||
* unit)}. It can be useful in testing, or to disable caching temporarily without a code change.
|
* {@link #expireAfterAccess expireAfterAccess}{@code (0,unit)}.
|
||||||
|
* It can be useful in testing, or to disable caching temporarily without a code change.
|
||||||
*
|
*
|
||||||
* @param size the maximum size of the cache
|
* @param size the maximum size of the cache
|
||||||
* @return This for chaining
|
* @return This for chaining
|
||||||
@ -180,7 +181,8 @@ public class CompatibleCacheBuilder<K, V> {
|
|||||||
* @throws IllegalStateException if a removal listener was already set
|
* @throws IllegalStateException if a removal listener was already set
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <K1 extends K, V1 extends V> CompatibleCacheBuilder<K1, V1> removalListener(RemovalListener<? super K1, ? super V1> listener) {
|
public <K1 extends K, V1 extends V> CompatibleCacheBuilder<K1, V1> removalListener(
|
||||||
|
RemovalListener<? super K1, ? super V1> listener) {
|
||||||
builder.removalListener(listener);
|
builder.removalListener(listener);
|
||||||
return (CompatibleCacheBuilder<K1, V1>) this;
|
return (CompatibleCacheBuilder<K1, V1>) this;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.github.games647.fastlogin.core;
|
package com.github.games647.fastlogin.core;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class PlayerProfile {
|
public class PlayerProfile {
|
||||||
@ -11,9 +12,9 @@ public class PlayerProfile {
|
|||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
private boolean premium;
|
private boolean premium;
|
||||||
private String lastIp;
|
private String lastIp;
|
||||||
private long lastLogin;
|
private Instant lastLogin;
|
||||||
|
|
||||||
public PlayerProfile(long userId, UUID uuid, String playerName, boolean premium, String lastIp, long lastLogin) {
|
public PlayerProfile(long userId, UUID uuid, String playerName, boolean premium, String lastIp, Instant lastLogin) {
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.playerName = playerName;
|
this.playerName = playerName;
|
||||||
@ -23,7 +24,7 @@ public class PlayerProfile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PlayerProfile(UUID uuid, String playerName, boolean premium, String lastIp) {
|
public PlayerProfile(UUID uuid, String playerName, boolean premium, String lastIp) {
|
||||||
this(-1, uuid, playerName, premium, lastIp, System.currentTimeMillis());
|
this(-1, uuid, playerName, premium, lastIp, Instant.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized String getPlayerName() {
|
public synchronized String getPlayerName() {
|
||||||
@ -66,11 +67,11 @@ public class PlayerProfile {
|
|||||||
this.lastIp = lastIp;
|
this.lastIp = lastIp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized long getLastLogin() {
|
public synchronized Instant getLastLogin() {
|
||||||
return lastLogin;
|
return lastLogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setLastLogin(long lastLogin) {
|
public synchronized void setLastLogin(Instant lastLogin) {
|
||||||
this.lastLogin = lastLogin;
|
this.lastLogin = lastLogin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@ 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.GameProfile 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> {
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ import java.net.Proxy;
|
|||||||
import java.net.Proxy.Type;
|
import java.net.Proxy.Type;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -53,7 +55,7 @@ public class MojangApiConnector {
|
|||||||
private final SSLSocketFactory sslFactory;
|
private final SSLSocketFactory sslFactory;
|
||||||
private final int rateLimit;
|
private final int rateLimit;
|
||||||
|
|
||||||
private long lastRateLimit;
|
private Instant lastRateLimit;
|
||||||
|
|
||||||
protected final Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create();
|
protected final Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create();
|
||||||
protected final Logger logger;
|
protected final Logger logger;
|
||||||
@ -72,9 +74,6 @@ public class MojangApiConnector {
|
|||||||
this.proxies = Iterables.cycle(proxyBuilder).iterator();
|
this.proxies = Iterables.cycle(proxyBuilder).iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return null on non-premium
|
|
||||||
*/
|
|
||||||
public Optional<UUID> getPremiumUUID(String playerName) {
|
public Optional<UUID> getPremiumUUID(String playerName) {
|
||||||
if (!validNameMatcher.matcher(playerName).matches()) {
|
if (!validNameMatcher.matcher(playerName).matches()) {
|
||||||
//check if it's a valid player name
|
//check if it's a valid player name
|
||||||
@ -83,7 +82,7 @@ public class MojangApiConnector {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
HttpsURLConnection connection;
|
HttpsURLConnection connection;
|
||||||
if (requests.size() >= rateLimit || System.currentTimeMillis() - lastRateLimit < 1_000 * 60 * 10) {
|
if (requests.size() >= rateLimit || Duration.between(lastRateLimit, Instant.now()).getSeconds() < 60 * 10) {
|
||||||
synchronized (proxies) {
|
synchronized (proxies) {
|
||||||
if (proxies.hasNext()) {
|
if (proxies.hasNext()) {
|
||||||
connection = getConnection(UUID_LINK + playerName, proxies.next());
|
connection = getConnection(UUID_LINK + playerName, proxies.next());
|
||||||
@ -103,7 +102,7 @@ public class MojangApiConnector {
|
|||||||
}
|
}
|
||||||
} else if (connection.getResponseCode() == RATE_LIMIT_CODE) {
|
} else if (connection.getResponseCode() == RATE_LIMIT_CODE) {
|
||||||
logger.info("RATE_LIMIT REACHED");
|
logger.info("RATE_LIMIT REACHED");
|
||||||
lastRateLimit = System.currentTimeMillis();
|
lastRateLimit = Instant.now();
|
||||||
if (!connection.usingProxy()) {
|
if (!connection.usingProxy()) {
|
||||||
return getPremiumUUID(playerName);
|
return getPremiumUUID(playerName);
|
||||||
}
|
}
|
||||||
@ -153,25 +152,25 @@ public class MojangApiConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SSLSocketFactory buildAddresses(Logger logger, Collection<String> localAddresses) {
|
private SSLSocketFactory buildAddresses(Logger logger, Collection<String> localAddresses) {
|
||||||
if (localAddresses.isEmpty()) {
|
if (!localAddresses.isEmpty()) {
|
||||||
return HttpsURLConnection.getDefaultSSLSocketFactory();
|
return HttpsURLConnection.getDefaultSSLSocketFactory();
|
||||||
} else {
|
|
||||||
Set<InetAddress> addresses = Sets.newHashSet();
|
|
||||||
for (String localAddress : localAddresses) {
|
|
||||||
try {
|
|
||||||
InetAddress address = InetAddress.getByName(localAddress);
|
|
||||||
if (!address.isAnyLocalAddress()) {
|
|
||||||
logger.warn("Submitted IP-Address is not local {0}", address);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
addresses.add(address);
|
|
||||||
} catch (UnknownHostException ex) {
|
|
||||||
logger.error("IP-Address is unknown to us", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BalancedSSLFactory(HttpsURLConnection.getDefaultSSLSocketFactory(), addresses);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Set<InetAddress> addresses = Sets.newHashSet();
|
||||||
|
for (String localAddress : localAddresses) {
|
||||||
|
try {
|
||||||
|
InetAddress address = InetAddress.getByName(localAddress);
|
||||||
|
if (!address.isAnyLocalAddress()) {
|
||||||
|
logger.warn("Submitted IP-Address is not local {}", address);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses.add(address);
|
||||||
|
} catch (UnknownHostException ex) {
|
||||||
|
logger.error("IP-Address is unknown to us", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BalancedSSLFactory(HttpsURLConnection.getDefaultSSLSocketFactory(), addresses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,11 @@ package com.github.games647.fastlogin.core.mojang;
|
|||||||
|
|
||||||
public class SkinProperties {
|
public class SkinProperties {
|
||||||
|
|
||||||
|
private final String name = "textures";
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
private String signature;
|
private String signature;
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return "textures";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
public String getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -11,18 +11,10 @@ import java.util.UUID;
|
|||||||
public class UUIDTypeAdapter extends TypeAdapter<UUID> {
|
public class UUIDTypeAdapter extends TypeAdapter<UUID> {
|
||||||
|
|
||||||
public void write(JsonWriter out, UUID value) throws IOException {
|
public void write(JsonWriter out, UUID value) throws IOException {
|
||||||
out.value(fromUUID(value));
|
out.value(value.toString().replace("-", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID read(JsonReader in) throws IOException {
|
public UUID read(JsonReader in) throws IOException {
|
||||||
return fromString(in.nextString());
|
return CommonUtil.parseId(in.nextString());
|
||||||
}
|
|
||||||
|
|
||||||
public static String fromUUID(UUID value) {
|
|
||||||
return value.toString().replace("-", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UUID fromString(String input) {
|
|
||||||
return CommonUtil.parseId(input);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
defaults = configProvider.load(defaultStream);
|
defaults = configProvider.load(defaultStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(plugin.getDataFolder(), fileName);
|
File file = plugin.getPluginFolder().resolve(fileName).toFile();
|
||||||
return configProvider.load(file, defaults);
|
return configProvider.load(file, defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void saveDefaultFile(String fileName) {
|
public void saveDefaultFile(String fileName) {
|
||||||
Path dataFolder = plugin.getDataFolder().toPath();
|
Path dataFolder = plugin.getPluginFolder();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(dataFolder);
|
Files.createDirectories(dataFolder);
|
||||||
|
@ -3,7 +3,7 @@ package com.github.games647.fastlogin.core.shared;
|
|||||||
import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
|
import com.github.games647.fastlogin.core.mojang.MojangApiConnector;
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
|
|
||||||
import java.io.File;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ public interface PlatformPlugin<C> {
|
|||||||
|
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
File getDataFolder();
|
Path getPluginFolder();
|
||||||
|
|
||||||
Logger getLog();
|
Logger getLog();
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ premiumUuid: false
|
|||||||
# #### Case 1
|
# #### Case 1
|
||||||
# nameChangeCheck = false ----- autoRegister = false
|
# nameChangeCheck = false ----- autoRegister = false
|
||||||
#
|
#
|
||||||
# GameProfile 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
|
||||||
# record.
|
# database record.
|
||||||
#
|
#
|
||||||
# #### Case 2
|
# #### Case 2
|
||||||
#
|
#
|
||||||
@ -128,8 +128,8 @@ premium-warning: true
|
|||||||
# Once the limit is reached, new players are always logged in as cracked until the rate-limit is expired.
|
# Once the limit is reached, new players are always logged in as cracked until the rate-limit is expired.
|
||||||
# (to the next ten minutes)
|
# (to the next ten minutes)
|
||||||
#
|
#
|
||||||
# The limit is IP-wide. If you have multiple IPv4-addresses you specify them here. FastLogin will then use it in rotating
|
# The limit is IP-wide. If you have multiple IPv4-addresses you specify them here. FastLogin will then use it in
|
||||||
# order --> 5 different IP-addresses 5 * 600 per 10 minutes
|
# rotating order --> 5 different IP-addresses 5 * 600 per 10 minutes
|
||||||
# If this list is empty only the default one will be used
|
# If this list is empty only the default one will be used
|
||||||
#
|
#
|
||||||
# Lists are created like this:
|
# Lists are created like this:
|
||||||
|
@ -86,7 +86,7 @@ invalid-session: '&4Invalid session'
|
|||||||
# The client sent a malicious packet without a login request packet
|
# The client sent a malicious packet without a login request packet
|
||||||
invalid-requst: '&4Invalid request'
|
invalid-requst: '&4Invalid request'
|
||||||
|
|
||||||
# Message if the bukkit isn't fully started to inject the packets
|
# Message if the Bukkit isn't fully started to inject the packets
|
||||||
not-started: '&cServer is not fully started yet. Please retry'
|
not-started: '&cServer is not fully started yet. Please retry'
|
||||||
|
|
||||||
# Warning message if a user invoked /premium command
|
# Warning message if a user invoked /premium command
|
||||||
|
Reference in New Issue
Block a user