Upload via Git Manager GUI - VerifyModule.java

This commit is contained in:
2026-04-01 10:15:45 +00:00
parent d190c5a882
commit cc1cbfa13a

View File

@@ -1,248 +1,248 @@
package net.viper.status.modules.verify; package net.viper.status.modules.verify;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;
import net.viper.status.module.Module; import net.viper.status.module.Module;
import javax.crypto.Mac; import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.io.*; import java.io.*;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
/** /**
* VerifyModule: Multi-Server Support. * VerifyModule: Multi-Server Support.
* Liest pro Server die passende ID und das Secret aus der verify.properties. * Liest pro Server die passende ID und das Secret aus der verify.properties.
*/ */
public class VerifyModule implements Module { public class VerifyModule implements Module {
private String wpVerifyUrl; private String wpVerifyUrl;
// Speichert für jeden Servernamen (z.B. "Lobby") die passende Konfiguration // Speichert für jeden Servernamen (z.B. "Lobby") die passende Konfiguration
private final Map<String, ServerConfig> serverConfigs = new HashMap<>(); private final Map<String, ServerConfig> serverConfigs = new HashMap<>();
@Override @Override
public String getName() { public String getName() {
return "VerifyModule"; return "VerifyModule";
} }
@Override @Override
public void onEnable(Plugin plugin) { public void onEnable(Plugin plugin) {
loadConfig(plugin); loadConfig(plugin);
// Befehl registrieren // Befehl registrieren
ProxyServer.getInstance().getPluginManager().registerCommand(plugin, new VerifyCommand()); ProxyServer.getInstance().getPluginManager().registerCommand(plugin, new VerifyCommand());
plugin.getLogger().info("VerifyModule aktiviert. " + serverConfigs.size() + " Server-Konfigurationen geladen."); plugin.getLogger().info("VerifyModule aktiviert. " + serverConfigs.size() + " Server-Konfigurationen geladen.");
} }
@Override @Override
public void onDisable(Plugin plugin) { public void onDisable(Plugin plugin) {
// Befehl muss nicht manuell entfernt werden, BungeeCord übernimmt das beim Plugin-Stop // Befehl muss nicht manuell entfernt werden, BungeeCord übernimmt das beim Plugin-Stop
} }
// --- Konfiguration Laden & Kopieren --- // --- Konfiguration Laden & Kopieren ---
private void loadConfig(Plugin plugin) { private void loadConfig(Plugin plugin) {
String fileName = "verify.properties"; String fileName = "verify.properties";
File configFile = new File(plugin.getDataFolder(), fileName); File configFile = new File(plugin.getDataFolder(), fileName);
Properties props = new Properties(); Properties props = new Properties();
// 1. Datei kopieren, falls sie noch nicht existiert // 1. Datei kopieren, falls sie noch nicht existiert
if (!configFile.exists()) { if (!configFile.exists()) {
plugin.getDataFolder().mkdirs(); plugin.getDataFolder().mkdirs();
try (InputStream in = plugin.getResourceAsStream(fileName); try (InputStream in = plugin.getResourceAsStream(fileName);
OutputStream out = new FileOutputStream(configFile)) { OutputStream out = new FileOutputStream(configFile)) {
if (in == null) { if (in == null) {
plugin.getLogger().warning("Standard-config '" + fileName + "' nicht in JAR gefunden. Erstelle manuell."); plugin.getLogger().warning("Standard-config '" + fileName + "' nicht in JAR gefunden. Erstelle manuell.");
return; return;
} }
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int length; int length;
while ((length = in.read(buffer)) > 0) { while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length); out.write(buffer, 0, length);
} }
plugin.getLogger().info("Konfigurationsdatei '" + fileName + "' erstellt."); plugin.getLogger().info("Konfigurationsdatei '" + fileName + "' erstellt.");
} catch (Exception e) { } catch (Exception e) {
plugin.getLogger().severe("Fehler beim Erstellen der Config: " + e.getMessage()); plugin.getLogger().severe("Fehler beim Erstellen der Config: " + e.getMessage());
return; return;
} }
} }
// 2. Eigentliche Config laden // 2. Eigentliche Config laden
try (InputStream in = new FileInputStream(configFile)) { try (InputStream in = new FileInputStream(configFile)) {
props.load(in); props.load(in);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return; return;
} }
// Globale URL // Globale URL
this.wpVerifyUrl = props.getProperty("wp_verify_url", "https://deine-wp-domain.tld"); this.wpVerifyUrl = props.getProperty("wp_verify_url", "https://deine-wp-domain.tld");
// Server-Configs parsen (z.B. server.Lobby.id) // Server-Configs parsen (z.B. server.Lobby.id)
this.serverConfigs.clear(); this.serverConfigs.clear();
for (String key : props.stringPropertyNames()) { for (String key : props.stringPropertyNames()) {
if (key.startsWith("server.")) { if (key.startsWith("server.")) {
// Key Struktur: server.<ServerName>.id oder .secret // Key Struktur: server.<ServerName>.id oder .secret
String[] parts = key.split("\\."); String[] parts = key.split("\\.");
if (parts.length == 3) { if (parts.length == 3) {
String serverName = parts[1]; String serverName = parts[1];
String type = parts[2]; String type = parts[2];
// Eintrag in der Map erstellen oder holen // Eintrag in der Map erstellen oder holen
ServerConfig config = serverConfigs.computeIfAbsent(serverName, k -> new ServerConfig()); ServerConfig config = serverConfigs.computeIfAbsent(serverName, k -> new ServerConfig());
if ("id".equalsIgnoreCase(type)) { if ("id".equalsIgnoreCase(type)) {
try { try {
config.serverId = Integer.parseInt(props.getProperty(key)); config.serverId = Integer.parseInt(props.getProperty(key));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
plugin.getLogger().warning("Ungültige Server ID für " + serverName); plugin.getLogger().warning("Ungültige Server ID für " + serverName);
} }
} else if ("secret".equalsIgnoreCase(type)) { } else if ("secret".equalsIgnoreCase(type)) {
config.sharedSecret = props.getProperty(key); config.sharedSecret = props.getProperty(key);
} }
} }
} }
} }
} }
// --- Hilfsklasse für die Daten eines Servers --- // --- Hilfsklasse für die Daten eines Servers ---
private static class ServerConfig { private static class ServerConfig {
int serverId = 0; int serverId = 0;
String sharedSecret = ""; String sharedSecret = "";
} }
// --- Die Command Klasse --- // --- Die Command Klasse ---
private class VerifyCommand extends Command { private class VerifyCommand extends Command {
public VerifyCommand() { public VerifyCommand() {
super("verify"); super("verify");
} }
@Override @Override
public void execute(CommandSender sender, String[] args) { public void execute(CommandSender sender, String[] args) {
if (!(sender instanceof ProxiedPlayer)) { if (!(sender instanceof ProxiedPlayer)) {
sender.sendMessage(ChatColor.RED + "Nur Spieler können diesen Befehl benutzen."); sender.sendMessage(ChatColor.RED + "Nur Spieler können diesen Befehl benutzen.");
return; return;
} }
ProxiedPlayer p = (ProxiedPlayer) sender; ProxiedPlayer p = (ProxiedPlayer) sender;
if (args.length != 1) { if (args.length != 1) {
p.sendMessage(ChatColor.YELLOW + "Benutzung: /verify <token>"); p.sendMessage(ChatColor.YELLOW + "Benutzung: /verify <token>");
return; return;
} }
// --- WICHTIG: Servernamen ermitteln --- // --- WICHTIG: Servernamen ermitteln ---
String serverName = p.getServer().getInfo().getName(); String serverName = p.getServer().getInfo().getName();
// Konfiguration für diesen Server laden // Konfiguration für diesen Server laden
ServerConfig config = serverConfigs.get(serverName); ServerConfig config = serverConfigs.get(serverName);
// Check ob Konfig existiert // Check ob Konfig existiert
if (config == null || config.serverId == 0 || config.sharedSecret.isEmpty()) { if (config == null || config.serverId == 0 || config.sharedSecret.isEmpty()) {
p.sendMessage(ChatColor.RED + "✗ Dieser Server ist nicht in der Verify-Konfiguration hinterlegt."); p.sendMessage(ChatColor.RED + "✗ Dieser Server ist nicht in der Verify-Konfiguration hinterlegt.");
p.sendMessage(ChatColor.GRAY + "Aktueller Servername: " + ChatColor.WHITE + serverName); p.sendMessage(ChatColor.GRAY + "Aktueller Servername: " + ChatColor.WHITE + serverName);
p.sendMessage(ChatColor.GRAY + "Bitte kontaktiere einen Admin."); p.sendMessage(ChatColor.GRAY + "Bitte kontaktiere einen Admin.");
return; return;
} }
String token = args[0].trim(); String token = args[0].trim();
String playerName = p.getName(); String playerName = p.getName();
HttpURLConnection conn = null; HttpURLConnection conn = null;
try { try {
Charset utf8 = Charset.forName("UTF-8"); Charset utf8 = Charset.forName("UTF-8");
// Wir signieren Name + Token mit dem SERVER-SPECIFISCHEN Secret // Wir signieren Name + Token mit dem SERVER-SPECIFISCHEN Secret
String signature = hmacSHA256(playerName + token, config.sharedSecret, utf8); String signature = hmacSHA256(playerName + token, config.sharedSecret, utf8);
// Payload aufbauen mit der SERVER-SPECIFISCHEN ID // Payload aufbauen mit der SERVER-SPECIFISCHEN ID
String payload = "{\"player\":\"" + escapeJson(playerName) + "\",\"token\":\"" + escapeJson(token) + "\",\"server_id\":" + config.serverId + ",\"signature\":\"" + signature + "\"}"; String payload = "{\"player\":\"" + escapeJson(playerName) + "\",\"token\":\"" + escapeJson(token) + "\",\"server_id\":" + config.serverId + ",\"signature\":\"" + signature + "\"}";
URL url = new URL(wpVerifyUrl + "/wp-json/mc-gallery/v1/verify"); URL url = new URL(wpVerifyUrl + "/wp-json/mc-gallery/v1/verify");
conn = (HttpURLConnection) url.openConnection(); conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000); conn.setConnectTimeout(5000);
conn.setReadTimeout(7000); conn.setReadTimeout(7000);
conn.setDoOutput(true); conn.setDoOutput(true);
conn.setRequestMethod("POST"); conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8"); conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
try (OutputStream os = conn.getOutputStream()) { try (OutputStream os = conn.getOutputStream()) {
os.write(payload.getBytes(utf8)); os.write(payload.getBytes(utf8));
} }
int code = conn.getResponseCode(); int code = conn.getResponseCode();
String resp; String resp;
if (code >= 200 && code < 300) { if (code >= 200 && code < 300) {
resp = streamToString(conn.getInputStream(), utf8); resp = streamToString(conn.getInputStream(), utf8);
} else { } else {
resp = streamToString(conn.getErrorStream(), utf8); resp = streamToString(conn.getErrorStream(), utf8);
} }
// Antwort verarbeiten // Antwort verarbeiten
if (resp != null && !resp.isEmpty() && resp.trim().startsWith("{")) { if (resp != null && !resp.isEmpty() && resp.trim().startsWith("{")) {
boolean isSuccess = resp.contains("\"success\":true"); boolean isSuccess = resp.contains("\"success\":true");
String message = "Ein unbekannter Fehler ist aufgetreten."; String message = "Ein unbekannter Fehler ist aufgetreten.";
int keyIndex = resp.indexOf("\"message\":\""); int keyIndex = resp.indexOf("\"message\":\"");
if (keyIndex != -1) { if (keyIndex != -1) {
int startIndex = keyIndex + 11; int startIndex = keyIndex + 11;
int endIndex = resp.indexOf("\"", startIndex); int endIndex = resp.indexOf("\"", startIndex);
if (endIndex != -1) { if (endIndex != -1) {
message = resp.substring(startIndex, endIndex); message = resp.substring(startIndex, endIndex);
} }
} }
if (isSuccess) { if (isSuccess) {
p.sendMessage(ChatColor.GREEN + "" + message); p.sendMessage(ChatColor.GREEN + "" + message);
p.sendMessage(ChatColor.GRAY + "Du kannst nun Bilder hochladen!"); p.sendMessage(ChatColor.GRAY + "Du kannst nun Bilder hochladen!");
} else { } else {
p.sendMessage(ChatColor.RED + "" + message); p.sendMessage(ChatColor.RED + "" + message);
} }
} else { } else {
p.sendMessage(ChatColor.RED + "✗ Fehler beim Verbinden mit der Webseite (Code: " + code + ")"); p.sendMessage(ChatColor.RED + "✗ Fehler beim Verbinden mit der Webseite (Code: " + code + ")");
} }
} catch (Exception ex) { } catch (Exception ex) {
p.sendMessage(ChatColor.RED + "✗ Ein interner Fehler ist aufgetreten."); p.sendMessage(ChatColor.RED + "✗ Ein interner Fehler ist aufgetreten.");
ProxyServer.getInstance().getLogger().warning("Verify error: " + ex.getMessage()); ProxyServer.getInstance().getLogger().warning("Verify error: " + ex.getMessage());
ex.printStackTrace(); ex.printStackTrace();
} finally { } finally {
if (conn != null) { if (conn != null) {
conn.disconnect(); conn.disconnect();
} }
} }
} }
} }
// --- Helper Methoden --- // --- Helper Methoden ---
private static String hmacSHA256(String data, String key, Charset charset) throws Exception { private static String hmacSHA256(String data, String key, Charset charset) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key.getBytes(charset), "HmacSHA256")); mac.init(new SecretKeySpec(key.getBytes(charset), "HmacSHA256"));
byte[] raw = mac.doFinal(data.getBytes(charset)); byte[] raw = mac.doFinal(data.getBytes(charset));
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (byte b : raw) sb.append(String.format("%02x", b)); for (byte b : raw) sb.append(String.format("%02x", b));
return sb.toString(); return sb.toString();
} }
private static String streamToString(InputStream in, Charset charset) throws IOException { private static String streamToString(InputStream in, Charset charset) throws IOException {
if (in == null) return ""; if (in == null) return "";
try (BufferedReader br = new BufferedReader(new InputStreamReader(in, charset))) { try (BufferedReader br = new BufferedReader(new InputStreamReader(in, charset))) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String line; String line;
while ((line = br.readLine()) != null) sb.append(line); while ((line = br.readLine()) != null) sb.append(line);
return sb.toString(); return sb.toString();
} }
} }
private static String escapeJson(String s) { private static String escapeJson(String s) {
return s.replace("\\", "\\\\").replace("\"","\\\"").replace("\n","\\n").replace("\r","\\r"); return s.replace("\\", "\\\\").replace("\"","\\\"").replace("\n","\\n").replace("\r","\\r");
} }
} }