From b65562850ff6cd7b8e4548fcddc854d633f00364 Mon Sep 17 00:00:00 2001 From: youpaishidifu <1@ypshidifu.cn> Date: Mon, 26 Oct 2026 13:10:41 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC57=E6=89=B9=E7=BB=AD5:=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D4=E4=B8=AAbug=201.=20onJoin=E5=B0=81=E7=A6=81=E7=BC=BA?= =?UTF-8?q?=E5=8F=A3=E9=80=9A=E7=9F=A5=E6=94=B9=E5=8F=AF=E7=82=B9=E5=87=BB?= =?UTF-8?q?Component=EF=BC=88Bug#1=EF=BC=89=202.=20webbind=20approve?= =?UTF-8?q?=E6=94=B9=E8=81=8A=E5=A4=A9=E6=A1=86=E8=BE=93=E5=85=A5=E5=AF=86?= =?UTF-8?q?=E7=A0=81+=E6=8B=92=E7=BB=9D=E9=80=89=E9=A1=B9=EF=BC=88Bug#2?= =?UTF-8?q?=EF=BC=89=203.=20PHP=20acctBindEmailFinish=20rejected=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E7=AE=80=E5=8C=96=E4=B8=BA=E5=8D=95=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=8C=89=E9=92=AE=EF=BC=88Bug#3=EF=BC=89=204.=20drawer-card?= =?UTF-8?q?=E6=AF=9B=E7=8E=BB=E7=92=83=E6=95=88=E6=9E=9C=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=EF=BC=88Bug#4=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Sdf1_login/Main.java | 103 ++++++++++++++++++----------- 1 file changed, 65 insertions(+), 38 deletions(-) diff --git a/src/main/java/Sdf1_login/Main.java b/src/main/java/Sdf1_login/Main.java index 62151fb..9aa8462 100644 --- a/src/main/java/Sdf1_login/Main.java +++ b/src/main/java/Sdf1_login/Main.java @@ -143,6 +143,8 @@ public class Main extends JavaPlugin private static final long IP_SKIP_MS = 300000L; // ★ 第56批:/webbind 批准密码验证失败计数(玩家名 -> 失败次数) private final ConcurrentHashMap webbindPwdFails = new ConcurrentHashMap<>(); + // ★ 第57批续5: /webbind approve 改聊天框输入密码(玩家名 -> 请求ID) + private final ConcurrentHashMap pendingWebbindApprove = new ConcurrentHashMap<>(); private SalesStatsManager salesStats; private final Map lastActivity = @@ -2987,10 +2989,22 @@ public class Main extends JavaPlugin String ip = getPlayerIP(p); // ★ 第57批:插件管理员登录 → CLI 通知待确认的封禁缺口 if (webManager != null && webManager.hasBanPending() && isAdmin(p)) { - p.sendMessage("\u00a7c\u00a7l[封禁-缺口] \u00a7f检测到 " + webManager.getBanPendingCount() - + " 条封禁数据缺口待确认"); - p.sendMessage("\u00a77执行 \u00a7a/sdf1_login confirm ban \u00a77拉回封禁数据"); - p.sendMessage("\u00a77或 \u00a7a/sdf1_login cancel ban \u00a77确认解封(清空PHP数据)"); + p.sendMessage(net.kyori.adventure.text.Component.text() + .append(net.kyori.adventure.text.Component.text("§c§l[封禁-缺口] §f检测到 ")) + .append(net.kyori.adventure.text.Component.text(String.valueOf(webManager.getBanPendingCount())) + .color(net.kyori.adventure.text.format.NamedTextColor.RED)) + .append(net.kyori.adventure.text.Component.text(" 条封禁数据缺口待确认")) + .build()); + p.sendMessage(net.kyori.adventure.text.Component.text() + .append(net.kyori.adventure.text.Component.text("§a[点击拉回封禁] §7").clickEvent( + net.kyori.adventure.text.event.ClickEvent.runCommand("/sdf1_login confirm ban"))) + .append(net.kyori.adventure.text.Component.text("§7= /sdf1_login confirm ban")) + .build()); + p.sendMessage(net.kyori.adventure.text.Component.text() + .append(net.kyori.adventure.text.Component.text("§c[点击确认解封] §7").clickEvent( + net.kyori.adventure.text.event.ClickEvent.runCommand("/sdf1_login cancel ban"))) + .append(net.kyori.adventure.text.Component.text("§7= /sdf1_login cancel ban")) + .build()); } // ===== 公告计分板(第35批)===== @@ -6244,6 +6258,49 @@ public class Main extends JavaPlugin return; } + // ★ 第57批续5: /webbind approve 密码输入拦截 + String pendingBindReq = pendingWebbindApprove.get(p.getName()); + if (pendingBindReq != null) { + e.setCancelled(true); + String input = msg.trim(); + // 拒绝选项 + if (input.equalsIgnoreCase("拒绝") || input.equalsIgnoreCase("reject")) { + pendingWebbindApprove.remove(p.getName()); + p.sendMessage("§e已拒绝,网页端直接返回"); + webManager.submitWebEmailBindResult(pendingBindReq, p.getName(), + "reject", "", status -> {}); + return; + } + // 密码验证 + int failCount2 = webbindPwdFails.getOrDefault(p.getName(), 0); + if (failCount2 >= 5) { + pendingWebbindApprove.remove(p.getName()); + p.sendMessage("§c§l[风控] §f连续5次失败,已被临时限制"); + return; + } + String pwdSalt2 = (String) db.getField(p.getName(), "password_salt"); + String pwdHash2 = PasswordUtils.hash(input, pwdSalt2); + String pwdResult2 = db.checkPasswordWithFallback(p.getName(), pwdHash2); + if (pwdResult2 == null) { + failCount2++; + webbindPwdFails.put(p.getName(), failCount2); + p.sendMessage("§c密码错误(" + failCount2 + "/5)"); + if (failCount2 >= 5) { + p.sendMessage("§c§l[风控] §f连续5次失败,已被临时限制"); + pendingWebbindApprove.remove(p.getName()); + } + return; + } + // 验证通过,清零计数 + webbindPwdFails.remove(p.getName()); + String reqId2 = pendingBindReq; + pendingWebbindApprove.remove(p.getName()); + p.sendMessage("§e正在提交批准…"); + webManager.submitWebEmailBindResult(reqId2, p.getName(), + "approve", "", status -> {}); + return; + } + // ★ 2FA 解绑确认输入拦截(30秒 confirm 窗口, // 输入 confirm=解绑,其它任意内容/超时=取消) if (twofa != null && twofa.isRemoveConfirming(p)) { @@ -9648,45 +9705,15 @@ public class Main extends JavaPlugin final boolean bindApprove = args[0].equalsIgnoreCase("approve"); // ★ 第56批:approve 时需要密码(Java端直接验证,不再依赖PHP复核) if (bindApprove) { - if (args.length < 3) { - wp.sendMessage("§c批准需要验证密码: /webbind approve " + bindReqId + " <密码>"); - return true; - } - final String bindPwd = args[2]; - // 5次失败风控 + // ★ 第57批续5: 改聊天框输入密码(不再要求命令行参数密码) int failCount = webbindPwdFails.getOrDefault(wp.getName(), 0); if (failCount >= 5) { wp.sendMessage("§c§l[风控] §f密码验证失败次数过多,已被临时限制。请稍后再试"); return true; } - // Java端直接验证密码 - String pwdSalt = (String) db.getField(wp.getName(), "password_salt"); - String pwdHash = PasswordUtils.hash(bindPwd, pwdSalt); - String pwdResult = db.checkPasswordWithFallback(wp.getName(), pwdHash); - if (pwdResult == null) { - failCount++; - webbindPwdFails.put(wp.getName(), failCount); - wp.sendMessage("§c密码错误(" + failCount + "/5)"); - if (failCount >= 5) { - wp.sendMessage("§c§l[风控] §f连续5次失败,已被临时限制"); - } - return true; - } - // 密码验证通过,清零失败计数 - webbindPwdFails.remove(wp.getName()); - wp.sendMessage("§e正在提交批准…"); - webManager.submitWebEmailBindResult(bindReqId, wp.getName(), - "approve", "", status -> { - if (status == null) { - wp.sendMessage("§c提交失败,请稍后重试"); - } else if ("approved".equals(status)) { - wp.sendMessage("§a已批准!§f邮箱绑定已完成"); - } else if ("expired".equals(status)) { - wp.sendMessage("§c请求已超时,未做任何处置"); - } else { - wp.sendMessage("§7请求当前状态: §f" + status); - } - }); + pendingWebbindApprove.put(wp.getName(), bindReqId); + wp.sendMessage("§e请在聊天框输入密码完成验证"); + wp.sendMessage("§7还是输入「拒绝」拒绝本次绑定"); return true; } // reject 不需要密码