From d47997294d648991898187922fe50338f34bf3fb Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Thu, 25 Jun 2026 14:41:25 +0800 Subject: [PATCH] =?UTF-8?q?v13:=20=E5=AE=89=E5=85=A8=E5=8A=A0=E5=9B=BA=20-?= =?UTF-8?q?=20PHP=E7=A6=81=E6=AD=A2=E8=87=AA=E9=AA=8C=E8=AF=81=E5=AF=86?= =?UTF-8?q?=E7=A0=81=20+=20Java=E6=9C=AC=E5=9C=B0=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=8C=81=E4=B9=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 安全修复(严重隐患): - PHP端: verifyWebPassword()函数体改为error(),禁止PHP直接验证密码 - Java端: pollWebLoginConfirmations()增加本地验证记录检查,PHP推送的登录确认必须有Java本地验证记录才允许自动登录 - Java端: 验证成功后写入login.db的web_verified_at字段(重启不丢失) - Java端: isWebLoginVerified()增加login.db回查(内存没有时从DB恢复) - Java端: clearWebLoginVerified()同时清除DB记录 - Java端: pollWebLoginConfirmations消费后立即清除验证记录(防重放) --- src/main/java/Sdf1_login/DatabaseManager.java | 3 + src/main/java/Sdf1_login/WebManager.java | 55 ++++++++++++++++--- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/main/java/Sdf1_login/DatabaseManager.java b/src/main/java/Sdf1_login/DatabaseManager.java index e3d774d..e6c2d3b 100644 --- a/src/main/java/Sdf1_login/DatabaseManager.java +++ b/src/main/java/Sdf1_login/DatabaseManager.java @@ -72,6 +72,9 @@ public class DatabaseManager { "TEXT DEFAULT ''"); safeAdd(st, "temp_pw_expire", "INTEGER DEFAULT 0"); + // ★ Web密码验证时间戳(Java验证成功后写入,重启不丢失) + safeAdd(st, "web_verified_at", + "INTEGER DEFAULT 0"); safeAdd(st, "temp_pw_used", "INTEGER DEFAULT 0"); safeAdd(st, "ip_address", diff --git a/src/main/java/Sdf1_login/WebManager.java b/src/main/java/Sdf1_login/WebManager.java index a83a044..fa23e7e 100644 --- a/src/main/java/Sdf1_login/WebManager.java +++ b/src/main/java/Sdf1_login/WebManager.java @@ -2894,15 +2894,33 @@ public class WebManager { * Java验证成功后立即记录,玩家进游戏时直接检查 */ public boolean isWebLoginVerified(String playerName) { + // ★ 优先检查内存(Java刚验证的) Long verifiedTime = verifiedWebLogins.get(playerName); - if (verifiedTime == null) return false; - - // 检查是否过期(5分钟) - if (System.currentTimeMillis() - verifiedTime > VERIFIED_LOGIN_EXPIRE_MS) { - verifiedWebLogins.remove(playerName); - return false; + if (verifiedTime != null) { + if (System.currentTimeMillis() - verifiedTime > VERIFIED_LOGIN_EXPIRE_MS) { + verifiedWebLogins.remove(playerName); + return false; + } + return true; } - return true; + + // ★ 内存没有 → 检查login.db(重启后恢复) + try { + Long dbTime = (Long) plugin.getDb().getField(playerName, "web_verified_at"); + if (dbTime != null && dbTime > 0) { + if (System.currentTimeMillis() - dbTime > VERIFIED_LOGIN_EXPIRE_MS) { + // 过期,清除DB记录 + plugin.getDb().setField(playerName, "web_verified_at", 0L); + return false; + } + // ★ 发现DB记录 → 同步到内存 + verifiedWebLogins.put(playerName, dbTime); + return true; + } + } catch (Exception e) { + // DB查询失败,安全降级为不自动登录 + } + return false; } /** @@ -2910,6 +2928,12 @@ public class WebManager { */ public void clearWebLoginVerified(String playerName) { verifiedWebLogins.remove(playerName); + // ★ 同步清除login.db记录 + try { + plugin.getDb().setField(playerName, "web_verified_at", 0L); + } catch (Exception e) { + // 静默 + } } /** @@ -3783,10 +3807,17 @@ public class WebManager { for (String playerName : players) { final String name = playerName; Bukkit.getScheduler().runTask(plugin, () -> { + // ★★★ 安全加固:PHP推送的登录确认,必须在Java本地有验证记录 ★★★ + // 防止PHP自验证假密码 → 写入web_login_confirmations → Java盲目自动登录 + if (!isWebLoginVerified(name)) { + plugin.getLogger().warning("[Web登录轮询] ⚠️ 玩家 " + name + " 无Java本地验证记录,拒绝自动登录(安全拦截)"); + return; + } plugin.getLogger().info("[Web登录轮询] 尝试处理玩家 " + name + " 的自动登录"); boolean ok = plugin.handleWebLoginConfirmation(name); if (ok) { - plugin.getLogger().info("[Web登录轮询] 玩家 " + name + " 通过WebToken验证,已自动登录"); + clearWebLoginVerified(name); // ★ 消费后立即清除 + plugin.getLogger().info("[Web登录轮询] 玩家 " + name + " 通过Java本地验证,已自动登录"); } else { plugin.getLogger().info("[Web登录轮询] 玩家 " + name + " 未在线,跳过自动登录"); } @@ -3880,7 +3911,13 @@ public class WebManager { // ★ 验证成功后,立即记录本地登录状态(不依赖PHP) if ("\"success\"".equals(result)) { verifiedWebLogins.put(fName, System.currentTimeMillis()); - plugin.getLogger().info("[Web密码验证] ★ 玩家 " + fName + " Web登录验证成功,已设置本地登录状态"); + // ★ 持久化到login.db(重启不丢失) + try { + plugin.getDb().setField(fName, "web_verified_at", System.currentTimeMillis()); + } catch (Exception dbEx) { + plugin.getLogger().warning("[Web密码验证] 写入login.db失败: " + dbEx.getMessage()); + } + plugin.getLogger().info("[Web密码验证] ★ 玩家 " + fName + " Web登录验证成功,已设置本地登录状态(内存+DB)"); } // 异步将结果写回PHP(供Web端查询)