修复正版验证三大问题:1)paste_code_page Content-Type改为text/html修复HTML源码输出 2)/mscode支持粘贴完整URL自动提取code参数 3)HTTP错误处理改进,非200也返回body显示PHP错误信息 4)verify_code改为JSON格式POST
This commit is contained in:
@@ -13,6 +13,7 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
@@ -1602,6 +1603,37 @@ public class Main extends JavaPlugin
|
||||
|
||||
// ===== Microsoft OAuth正版验证 =====
|
||||
|
||||
/**
|
||||
* 从用户输入中提取Microsoft OAuth授权码
|
||||
* 支持:纯授权码、完整URL(含code=参数)
|
||||
*/
|
||||
private String extractCodeFromInput(String input) {
|
||||
if (input == null || input.isEmpty()) return null;
|
||||
input = input.trim();
|
||||
|
||||
// 如果包含code=参数,从中提取
|
||||
if (input.contains("code=") || input.startsWith("http")) {
|
||||
try {
|
||||
// 尝试解析URL中的query参数
|
||||
int qIdx = input.indexOf('?');
|
||||
if (qIdx >= 0) {
|
||||
String query = input.substring(qIdx + 1);
|
||||
for (String param : query.split("&")) {
|
||||
String[] kv = param.split("=", 2);
|
||||
if (kv.length == 2 && kv[0].equals("code")) {
|
||||
return java.net.URLDecoder.decode(kv[1], StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 解析失败,继续尝试其他方式
|
||||
}
|
||||
}
|
||||
|
||||
// 直接作为授权码返回
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理正版验证命令:调用PHP后端获取授权URL,显示给玩家,启动轮询
|
||||
*/
|
||||
@@ -5998,7 +6030,7 @@ public class Main extends JavaPlugin
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===== /mscode <授权码>:粘贴Microsoft OAuth授权码 =====
|
||||
// ===== /mscode <授权码或URL>:粘贴Microsoft OAuth授权码或完整URL =====
|
||||
if (cmdName.equals("mscode")) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage("§c仅玩家可用");
|
||||
@@ -6010,13 +6042,16 @@ public class Main extends JavaPlugin
|
||||
return true;
|
||||
}
|
||||
if (args.length < 1) {
|
||||
p.sendMessage("§c用法: /mscode <授权码>");
|
||||
p.sendMessage("§7从Microsoft登录页面复制授权码后粘贴到这里");
|
||||
p.sendMessage("§c用法: /mscode <授权码或完整URL>");
|
||||
p.sendMessage("§7粘贴Microsoft登录后的授权码,或粘贴包含code=的完整URL");
|
||||
return true;
|
||||
}
|
||||
String code = args[0].trim();
|
||||
if (code.length() < 10) {
|
||||
p.sendMessage("§c授权码格式不正确,请复制完整的授权码");
|
||||
String rawInput = String.join(" ", args).trim();
|
||||
// 自动从URL中提取code参数
|
||||
String code = extractCodeFromInput(rawInput);
|
||||
if (code == null || code.length() < 10) {
|
||||
p.sendMessage("§c无法从输入中提取有效的授权码");
|
||||
p.sendMessage("§7请粘贴授权码或包含code=的完整URL");
|
||||
return true;
|
||||
}
|
||||
// 检查是否有进行中的会话
|
||||
|
||||
@@ -555,11 +555,15 @@ public class WebManager {
|
||||
detectPhpBusy(body); // ★ 锁库检测
|
||||
return body;
|
||||
}
|
||||
// ★ 500时记录响应体(PHP错误信息在body里)
|
||||
// ★ 4xx/5xx也返回body(PHP的error()返回有用的JSON错误信息)
|
||||
String shortUrl = urlStr.length() > 120 ? urlStr.substring(0, 120) + "..." : urlStr;
|
||||
String body = resp.body();
|
||||
String shortBody = (body != null && body.length() > 200) ? body.substring(0, 200) : body;
|
||||
plugin.getLogger().warning("[Web通信] GET HTTP " + resp.statusCode() + ": " + shortUrl + " | 响应: " + shortBody);
|
||||
// 返回body让调用方可以解析PHP错误信息
|
||||
if (body != null && !body.isEmpty()) {
|
||||
return body;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
// ★ SSL断路器:跟踪连续失败(所有连接异常都计数)
|
||||
@@ -633,11 +637,14 @@ public class WebManager {
|
||||
if (resp.statusCode() >= 200 && resp.statusCode() < 300) {
|
||||
return resp.body();
|
||||
}
|
||||
// ★ 非2xx记录响应体
|
||||
// ★ 非2xx也返回body(PHP的error()返回有用的JSON错误信息)
|
||||
String shortUrl = urlStr.length() > 120 ? urlStr.substring(0, 120) + "..." : urlStr;
|
||||
String body = resp.body();
|
||||
String shortBody = (body != null && body.length() > 200) ? body.substring(0, 200) : body;
|
||||
plugin.getLogger().warning("[Web通信] POST HTTP " + resp.statusCode() + ": " + shortUrl + " | 响应: " + shortBody);
|
||||
if (body != null && !body.isEmpty()) {
|
||||
return body;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
// ★ SSL断路器:跟踪连续失败(所有连接异常都计数)
|
||||
@@ -674,11 +681,14 @@ public class WebManager {
|
||||
sslDowngraded = false; // 恢复正常HTTPS
|
||||
return resp.body();
|
||||
}
|
||||
// ★ 非2xx记录响应体
|
||||
// ★ 非2xx也返回body(PHP的error()返回有用的JSON错误信息)
|
||||
String shortUrl = urlStr.length() > 120 ? urlStr.substring(0, 120) + "..." : urlStr;
|
||||
String body = resp.body();
|
||||
String shortBody = (body != null && body.length() > 200) ? body.substring(0, 200) : body;
|
||||
plugin.getLogger().warning("[Web通信] POST HTTP " + resp.statusCode() + ": " + shortUrl + " | 响应: " + shortBody);
|
||||
if (body != null && !body.isEmpty()) {
|
||||
return body;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
// ★ SSL断路器:跟踪连续失败(所有连接异常都计数)
|
||||
@@ -4945,7 +4955,16 @@ public class WebManager {
|
||||
return;
|
||||
}
|
||||
|
||||
com.google.gson.JsonObject json = com.google.gson.JsonParser.parseString(response).getAsJsonObject();
|
||||
com.google.gson.JsonObject json;
|
||||
try {
|
||||
json = com.google.gson.JsonParser.parseString(response).getAsJsonObject();
|
||||
} catch (Exception parseEx) {
|
||||
// PHP返回了非JSON(如500错误页面),显示截断内容
|
||||
String preview = response.length() > 150 ? response.substring(0, 150) + "..." : response;
|
||||
player.sendMessage("§c后端返回异常: " + preview);
|
||||
plugin.getLogger().warning("[正版验证] PHP返回非JSON: " + preview);
|
||||
return;
|
||||
}
|
||||
if (!json.get("success").getAsBoolean()) {
|
||||
String error = json.has("error") ? json.get("error").getAsString() : "未知错误";
|
||||
player.sendMessage("§c验证失败: " + error);
|
||||
@@ -4965,13 +4984,9 @@ public class WebManager {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
if (player.isOnline()) {
|
||||
player.sendMessage("§6§l===== 正版验证 =====");
|
||||
player.sendMessage("§7方式一: 点击链接完成验证后,复制授权码粘贴到聊天:");
|
||||
player.sendMessage("§b/mscode <授权码>");
|
||||
player.sendMessage("§7方式二: 在浏览器中打开验证页面:");
|
||||
if (finalPasteUrl != null) {
|
||||
player.sendMessage("§b" + finalPasteUrl);
|
||||
}
|
||||
player.sendMessage("§7步骤: 打开链接 → 登录Microsoft → 复制授权码 → /mscode粘贴");
|
||||
player.sendMessage("§7方式一: 点击下方链接打开粘贴页面");
|
||||
player.sendMessage("§7方式二: /mscode <粘贴完整URL或授权码>");
|
||||
player.sendMessage("§7步骤: 打开链接 → 登录 → 复制地址栏URL → 粘贴");
|
||||
player.sendMessage("§7链接10分钟内有效");
|
||||
player.sendMessage("§6§l====================");
|
||||
// 尝试发送可点击的URL(授权链接)
|
||||
@@ -5153,18 +5168,27 @@ public class WebManager {
|
||||
try {
|
||||
String url = webBaseUrl + "/api/minecraft_auth.php?action=verify_code";
|
||||
|
||||
// POST参数
|
||||
String postData = "session_id=" + java.net.URLEncoder.encode(sessionId, StandardCharsets.UTF_8)
|
||||
+ "&code=" + java.net.URLEncoder.encode(code, StandardCharsets.UTF_8)
|
||||
+ "&secret=" + secret;
|
||||
// POST参数(JSON格式,与doPost的Content-Type一致)
|
||||
com.google.gson.JsonObject postData = new com.google.gson.JsonObject();
|
||||
postData.addProperty("session_id", sessionId);
|
||||
postData.addProperty("code", code);
|
||||
postData.addProperty("secret", secret);
|
||||
|
||||
String response = doPost(url, postData);
|
||||
String response = doPost(url, postData.toString());
|
||||
if (response == null) {
|
||||
player.sendMessage("§c无法连接Web后端");
|
||||
return;
|
||||
}
|
||||
|
||||
com.google.gson.JsonObject json = com.google.gson.JsonParser.parseString(response).getAsJsonObject();
|
||||
com.google.gson.JsonObject json;
|
||||
try {
|
||||
json = com.google.gson.JsonParser.parseString(response).getAsJsonObject();
|
||||
} catch (Exception parseEx) {
|
||||
String preview = response.length() > 150 ? response.substring(0, 150) + "..." : response;
|
||||
player.sendMessage("§c后端返回异常: " + preview);
|
||||
plugin.getLogger().warning("[正版验证] verify_code返回非JSON: " + preview);
|
||||
return;
|
||||
}
|
||||
if (json.get("success").getAsBoolean()) {
|
||||
com.google.gson.JsonObject data = json.getAsJsonObject("data");
|
||||
String mcUuid = data.get("mc_uuid").getAsString();
|
||||
|
||||
Reference in New Issue
Block a user