From 0486693ce304e32a96bcbe55b961098dbff4cf01 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 22 Nov 2025 03:26:25 +0000 Subject: [PATCH] Refactor event handling and implement password hashing - Moved event listeners from `BlbiLogin` to `PlayerActivityListener` to separate concerns. - Implemented `PasswordUtil` for SHA-256 password hashing with salt. - Updated `Sqlite` to use hashed passwords for registration and verification. - Added backward compatibility for existing plain text passwords. - Refactored `Login` and `Register` commands to use dependency injection for the plugin instance. --- gradlew | 0 .../com/blbilink/blbilogin/BlbiLogin.java | 42 ++----------- .../blbilink/blbilogin/load/LoadFunction.java | 6 +- .../blbilink/blbilogin/modules/Sqlite.java | 12 ++-- .../blbilogin/modules/commands/Login.java | 8 ++- .../blbilogin/modules/commands/Register.java | 8 ++- .../events/PlayerActivityListener.java | 49 +++++++++++++++ .../blbilogin/utils/PasswordUtil.java | 61 +++++++++++++++++++ 8 files changed, 139 insertions(+), 47 deletions(-) mode change 100644 => 100755 gradlew create mode 100644 src/main/java/com/blbilink/blbilogin/modules/events/PlayerActivityListener.java create mode 100644 src/main/java/com/blbilink/blbilogin/utils/PasswordUtil.java diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/java/com/blbilink/blbilogin/BlbiLogin.java b/src/main/java/com/blbilink/blbilogin/BlbiLogin.java index 70b34bf..11365ea 100644 --- a/src/main/java/com/blbilink/blbilogin/BlbiLogin.java +++ b/src/main/java/com/blbilink/blbilogin/BlbiLogin.java @@ -5,18 +5,13 @@ import com.blbilink.blbilogin.load.LoadFunction; import com.blbilink.blbilogin.modules.events.CheckOnline; import com.blbilink.blbilogin.modules.events.LoginAction; -import com.blbilink.blbilogin.vars.Configvar; +import com.blbilink.blbilogin.modules.events.PlayerActivityListener; import org.blbilink.blbiLibrary.I18n; import org.blbilink.blbiLibrary.Metrics; import org.blbilink.blbiLibrary.utils.ConfigUtil; import org.blbilink.blbiLibrary.utils.FoliaUtil; import org.blbilink.blbiLibrary.utils.TextUtil; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.plugin.java.JavaPlugin; import java.util.Arrays; @@ -40,6 +35,9 @@ public void onEnable() { CheckOnline.INSTANCE.sync(this); foliaUtil = new FoliaUtil(this); + // Register event listener + getServer().getPluginManager().registerEvents(new PlayerActivityListener(this), this); + // 检查是否是 Folia 服务端核心 foliaUtil.checkFolia(true); @@ -74,36 +72,4 @@ public void onDisable() { List.of("EggFine"), List.of("Mgazul"))); } - - @EventHandler - public void onPlayerMove(PlayerMoveEvent e) { - - if (Configvar.noLoginPlayerList.contains(e.getPlayer().getName()) && Configvar.config.getBoolean("noLoginPlayerCantMove")) { - String msgNoLoginTryMove = i18n.as("logNoLoginTryMove", false, e.getPlayer().getName()); - this.getLogger().info(msgNoLoginTryMove); - e.setCancelled(true); - } - } - - @EventHandler - public void onPlayerBreak(BlockBreakEvent e) { - if (Configvar.noLoginPlayerList.contains(e.getPlayer().getName()) && Configvar.config.getBoolean("noLoginPlayerCantBreak")) { - getLogger().info("未登录玩家 " + e.getPlayer().getName() + " 尝试挖掘方块" + e.getBlock().getType().name() + "已进行阻止."); - e.setCancelled(true); - } - } - - @EventHandler - public void onPlayerHurt(EntityDamageEvent e) { - if (e.getEntity() instanceof Player player) { - - if (Configvar.noLoginPlayerList.contains(player.getName()) && Configvar.config.getBoolean("noLoginPlayerCantHurt")) { - EntityDamageEvent.DamageCause currentDamageCause = e.getCause(); - String damageCauseName = currentDamageCause.name(); - - getLogger().info("未登录玩家 " + player.getName() + " 受到伤害 " + damageCauseName + " 已进行阻止."); - e.setCancelled(true); - } - } - } } \ No newline at end of file diff --git a/src/main/java/com/blbilink/blbilogin/load/LoadFunction.java b/src/main/java/com/blbilink/blbilogin/load/LoadFunction.java index 5239e5d..53ee71b 100644 --- a/src/main/java/com/blbilink/blbilogin/load/LoadFunction.java +++ b/src/main/java/com/blbilink/blbilogin/load/LoadFunction.java @@ -34,13 +34,13 @@ private void loadCommands(){ Objects.requireNonNull(plugin.getCommand("blbilogin")).setTabCompleter(blbiLoginCommand); - Objects.requireNonNull(plugin.getCommand("register")).setExecutor(new Register()); - Objects.requireNonNull(plugin.getCommand("login")).setExecutor(new Login()); + Objects.requireNonNull(plugin.getCommand("register")).setExecutor(new Register(plugin)); + Objects.requireNonNull(plugin.getCommand("login")).setExecutor(new Login(plugin)); Objects.requireNonNull(plugin.getCommand("resetpassword")).setExecutor(new ResetPassword()); } private void loadListeners(){ // 注册Bukkit事件监听器 - Bukkit.getPluginManager().registerEvents(BlbiLogin.plugin, plugin); + // Event listener from BlbiLogin has been moved to PlayerActivityListener and registered in BlbiLogin Bukkit.getPluginManager().registerEvents(new PlayerSender(), plugin); Bukkit.getPluginManager().registerEvents(new PlayerUseCommands(), plugin); Bukkit.getPluginManager().registerEvents(new PlayerJoin(BlbiLogin.plugin), plugin); diff --git a/src/main/java/com/blbilink/blbilogin/modules/Sqlite.java b/src/main/java/com/blbilink/blbilogin/modules/Sqlite.java index 927344f..dfe358b 100644 --- a/src/main/java/com/blbilink/blbilogin/modules/Sqlite.java +++ b/src/main/java/com/blbilink/blbilogin/modules/Sqlite.java @@ -2,6 +2,7 @@ import com.blbilink.blbilogin.load.LoadFunction; +import com.blbilink.blbilogin.utils.PasswordUtil; import java.sql.Connection; import java.sql.DriverManager; @@ -18,11 +19,13 @@ public static Sqlite getSqlite() { } public Sqlite() { try { + // Load the SQLite JDBC driver + Class.forName("org.sqlite.JDBC"); connection = DriverManager.getConnection("jdbc:sqlite:plugins/blbiLogin/players.db"); try (PreparedStatement statement = connection.prepareStatement("CREATE TABLE IF NOT EXISTS players (uuid TEXT PRIMARY KEY, username TEXT, password TEXT)")) { statement.executeUpdate(); } - } catch (SQLException e) { + } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); } } @@ -42,7 +45,7 @@ public void registerPlayer(String uuid, String username, String password) { try (PreparedStatement statement = connection.prepareStatement("INSERT INTO players (uuid, username, password) VALUES (?, ?, ?)")) { statement.setString(1, uuid); statement.setString(2, username); - statement.setString(3, password); + statement.setString(3, PasswordUtil.hashPassword(password)); statement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); @@ -54,7 +57,8 @@ public boolean checkPassword(String uuid, String password) { statement.setString(1, uuid); ResultSet results = statement.executeQuery(); if (results.next()) { - return results.getString("password").equals(password); + String storedPassword = results.getString("password"); + return PasswordUtil.checkPassword(password, storedPassword); } } catch (SQLException e) { e.printStackTrace(); @@ -64,7 +68,7 @@ public boolean checkPassword(String uuid, String password) { public boolean resetPassword(String uuid, String newPassword) { try (PreparedStatement statement = connection.prepareStatement("UPDATE players SET password = ? WHERE uuid = ?")) { - statement.setString(1, newPassword); + statement.setString(1, PasswordUtil.hashPassword(newPassword)); statement.setString(2, uuid); int rowsUpdated = statement.executeUpdate(); return rowsUpdated > 0; diff --git a/src/main/java/com/blbilink/blbilogin/modules/commands/Login.java b/src/main/java/com/blbilink/blbilogin/modules/commands/Login.java index 7c7f6aa..4ead5da 100644 --- a/src/main/java/com/blbilink/blbilogin/modules/commands/Login.java +++ b/src/main/java/com/blbilink/blbilogin/modules/commands/Login.java @@ -9,10 +9,16 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import static com.blbilink.blbilogin.BlbiLogin.plugin; +import com.blbilink.blbilogin.BlbiLogin; public class Login implements CommandExecutor { private final LoginAction login = LoginAction.INSTANCE; + private final BlbiLogin plugin; + + public Login(BlbiLogin plugin) { + this.plugin = plugin; + } + @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { Player player = (Player) sender; diff --git a/src/main/java/com/blbilink/blbilogin/modules/commands/Register.java b/src/main/java/com/blbilink/blbilogin/modules/commands/Register.java index 6590cc1..8a0b95f 100644 --- a/src/main/java/com/blbilink/blbilogin/modules/commands/Register.java +++ b/src/main/java/com/blbilink/blbilogin/modules/commands/Register.java @@ -7,9 +7,15 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import static com.blbilink.blbilogin.BlbiLogin.plugin; +import com.blbilink.blbilogin.BlbiLogin; public class Register implements CommandExecutor { + private final BlbiLogin plugin; + + public Register(BlbiLogin plugin) { + this.plugin = plugin; + } + @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { if (!(sender instanceof Player)) { diff --git a/src/main/java/com/blbilink/blbilogin/modules/events/PlayerActivityListener.java b/src/main/java/com/blbilink/blbilogin/modules/events/PlayerActivityListener.java new file mode 100644 index 0000000..0b40f09 --- /dev/null +++ b/src/main/java/com/blbilink/blbilogin/modules/events/PlayerActivityListener.java @@ -0,0 +1,49 @@ +package com.blbilink.blbilogin.modules.events; + +import com.blbilink.blbilogin.BlbiLogin; +import com.blbilink.blbilogin.vars.Configvar; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerMoveEvent; + +public class PlayerActivityListener implements Listener { + + private final BlbiLogin plugin; + + public PlayerActivityListener(BlbiLogin plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent e) { + if (Configvar.noLoginPlayerList.contains(e.getPlayer().getName()) && Configvar.config.getBoolean("noLoginPlayerCantMove")) { + String msgNoLoginTryMove = plugin.i18n.as("logNoLoginTryMove", false, e.getPlayer().getName()); + plugin.getLogger().info(msgNoLoginTryMove); + e.setCancelled(true); + } + } + + @EventHandler + public void onPlayerBreak(BlockBreakEvent e) { + if (Configvar.noLoginPlayerList.contains(e.getPlayer().getName()) && Configvar.config.getBoolean("noLoginPlayerCantBreak")) { + plugin.getLogger().info("未登录玩家 " + e.getPlayer().getName() + " 尝试挖掘方块" + e.getBlock().getType().name() + "已进行阻止."); + e.setCancelled(true); + } + } + + @EventHandler + public void onPlayerHurt(EntityDamageEvent e) { + if (e.getEntity() instanceof Player player) { + if (Configvar.noLoginPlayerList.contains(player.getName()) && Configvar.config.getBoolean("noLoginPlayerCantHurt")) { + EntityDamageEvent.DamageCause currentDamageCause = e.getCause(); + String damageCauseName = currentDamageCause.name(); + + plugin.getLogger().info("未登录玩家 " + player.getName() + " 受到伤害 " + damageCauseName + " 已进行阻止."); + e.setCancelled(true); + } + } + } +} diff --git a/src/main/java/com/blbilink/blbilogin/utils/PasswordUtil.java b/src/main/java/com/blbilink/blbilogin/utils/PasswordUtil.java new file mode 100644 index 0000000..6b1a47c --- /dev/null +++ b/src/main/java/com/blbilink/blbilogin/utils/PasswordUtil.java @@ -0,0 +1,61 @@ +package com.blbilink.blbilogin.utils; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Base64; + +public class PasswordUtil { + + private static final int SALT_LENGTH = 16; + private static final String HASH_ALGORITHM = "SHA-256"; + + /** + * Generates a salt and hashes the password with it. + * Returns a string in the format: salt$hash + * + * @param password The plain text password. + * @return The salted and hashed password. + */ + public static String hashPassword(String password) { + byte[] salt = generateSalt(); + String hash = hash(password, salt); + return Base64.getEncoder().encodeToString(salt) + "$" + hash; + } + + /** + * Verifies the password against the stored salted hash. + * + * @param password The plain text password. + * @param storedHash The stored password string (salt$hash). + * @return True if the password matches, false otherwise. + */ + public static boolean checkPassword(String password, String storedHash) { + String[] parts = storedHash.split("\\$"); + if (parts.length != 2) { + // Fallback for old plain text passwords (migration strategy) + return password.equals(storedHash); + } + byte[] salt = Base64.getDecoder().decode(parts[0]); + String hash = hash(password, salt); + return hash.equals(parts[1]); + } + + private static byte[] generateSalt() { + SecureRandom random = new SecureRandom(); + byte[] salt = new byte[SALT_LENGTH]; + random.nextBytes(salt); + return salt; + } + + private static String hash(String password, byte[] salt) { + try { + MessageDigest md = MessageDigest.getInstance(HASH_ALGORITHM); + md.update(salt); + byte[] hashedPassword = md.digest(password.getBytes()); + return Base64.getEncoder().encodeToString(hashedPassword); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("Hashing algorithm not found", e); + } + } +}