diff --git a/gc-plugin/src/main/java/com/mojo/consoleplus/AuthHandler.java b/gc-plugin/src/main/java/com/mojo/consoleplus/AuthHandler.java new file mode 100644 index 0000000..ba1c72c --- /dev/null +++ b/gc-plugin/src/main/java/com/mojo/consoleplus/AuthHandler.java @@ -0,0 +1,53 @@ +package com.mojo.consoleplus; +import java.security.MessageDigest; +import java.util.UUID; +import com.mojo.consoleplus.ConsolePlus; + +public class AuthHandler { + public static String signatureStub; + + public AuthHandler(){ + try { + signatureStub = UUID.randomUUID().toString(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public AuthHandler(String stub) { + signatureStub = stub; + } + + public Boolean auth(int uid, long expire, String dg) { + return digestUid(uid+":"+expire).equals(dg); + } + + public String genKey(int uid, long expire){ + String part1 = uid +":"+expire; + + return part1 + ":" + digestUid(part1); + } + + private String digestUid(String payload) { + MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-256"); + return bytesToHex(digest.digest((payload + ":" + signatureStub).getBytes("UTF-8"))); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + private static String bytesToHex(byte[] hash) { + StringBuilder hexString = new StringBuilder(2 * hash.length); + for (int i = 0; i < hash.length; i++) { + String hex = Integer.toHexString(0xff & hash[i]); + if(hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } +} diff --git a/gc-plugin/src/main/java/com/mojo/consoleplus/ConsolePlus.java b/gc-plugin/src/main/java/com/mojo/consoleplus/ConsolePlus.java index 4a665c0..b39708e 100644 --- a/gc-plugin/src/main/java/com/mojo/consoleplus/ConsolePlus.java +++ b/gc-plugin/src/main/java/com/mojo/consoleplus/ConsolePlus.java @@ -22,6 +22,7 @@ import com.mojo.consoleplus.config.MojoConfig; public class ConsolePlus extends Plugin{ public static MojoConfig config = MojoConfig.loadConfig(); public static String versionTag; + public static AuthHandler authHandler; @Override public void onLoad() { @@ -58,7 +59,7 @@ public class ConsolePlus extends Plugin{ Grasscutter.getHttpServer().addRouter(RequestHandler.class); CommandMap.getInstance().registerCommand("mojoconsole", new PluginCommand()); this.getLogger().info("[MojoConsole] enabled. Version: " + versionTag); - + authHandler = new AuthHandler(); } @Override diff --git a/gc-plugin/src/main/java/com/mojo/consoleplus/RequestHandler.java b/gc-plugin/src/main/java/com/mojo/consoleplus/RequestHandler.java index 7a9d45f..8b4b0c3 100644 --- a/gc-plugin/src/main/java/com/mojo/consoleplus/RequestHandler.java +++ b/gc-plugin/src/main/java/com/mojo/consoleplus/RequestHandler.java @@ -1,5 +1,8 @@ package com.mojo.consoleplus; +import static java.lang.Integer.parseInt; +import static java.lang.Long.parseLong; + import java.io.IOException; import java.util.Map; @@ -34,43 +37,61 @@ public final class RequestHandler implements Router { public static void processRequest(Request req, Response res) throws IOException { RequestJson request = req.body(RequestJson.class); res.type("application/json"); - if (request.k != null) { + Player player = null; + if (request.k != null) { // version 1 token Account account = DatabaseHelper.getAccountBySessionKey(request.k); Map playersMap = Grasscutter.getGameServer().getPlayers(); - Player player = null; // String invokeResult = ""; - MessageHandler resultCollector = new MessageHandler(); if (account != null) { for (int playerid: playersMap.keySet()) { if (playersMap.get(playerid).getUid() == account.getPlayerUid()) { player = playersMap.get(playerid); } } - if (player != null) { - // player.setInvokeResult("[MojoConsole]"); - player.setMessageHandler(resultCollector); // hook the message - switch (request.request){ - case "invoke": - try{ - // TODO: Enable execut commands to third party - CommandMap.getInstance().invoke(player, player, request.payload); - } catch (Exception e) { - res.json(new ResponseJson("error", 500, e.getStackTrace().toString())); - break; - } - case "ping": - // res.json(new ResponseJson("success", 200)); - res.json(new ResponseJson("success", 200, resultCollector.getMessage())); - break; - default: - res.json(new ResponseJson("400 Bad Request", 400)); - break; + } + } + + if (request.k2 != null) { // version 2 token + int uid; + long expire; + String hashDigest; + uid = parseInt(request.k2.split(":")[0]); + expire = parseLong(request.k2.split(":")[1]); + hashDigest = request.k2.split(":")[2]; + if (ConsolePlus.authHandler.auth(uid, expire, hashDigest)){ + Map playersMap = Grasscutter.getGameServer().getPlayers(); + for (int playerid: playersMap.keySet()) { + if (playersMap.get(playerid).getUid() == uid) { + player = playersMap.get(playerid); } - player.setMessageHandler(null); - return; } } } + + if (player != null) { + MessageHandler resultCollector = new MessageHandler(); + player.setMessageHandler(resultCollector); // hook the message + switch (request.request){ + case "invoke": + try{ + // TODO: Enable execut commands to third party + CommandMap.getInstance().invoke(player, player, request.payload); + } catch (Exception e) { + res.json(new ResponseJson("error", 500, e.getStackTrace().toString())); + break; + } + case "ping": + // res.json(new ResponseJson("success", 200)); + res.json(new ResponseJson("success", 200, resultCollector.getMessage())); + break; + default: + res.json(new ResponseJson("400 Bad Request", 400)); + break; + } + player.setMessageHandler(null); + return; + } + res.json(new ResponseJson("403 Forbidden", 403)); } } diff --git a/gc-plugin/src/main/java/com/mojo/consoleplus/command/PluginCommand.java b/gc-plugin/src/main/java/com/mojo/consoleplus/command/PluginCommand.java index e365d98..8720486 100644 --- a/gc-plugin/src/main/java/com/mojo/consoleplus/command/PluginCommand.java +++ b/gc-plugin/src/main/java/com/mojo/consoleplus/command/PluginCommand.java @@ -1,6 +1,7 @@ package com.mojo.consoleplus.command; import java.net.URLEncoder; +import java.util.HashMap; import java.util.List; import emu.grasscutter.Grasscutter; @@ -17,24 +18,27 @@ import com.google.gson.Gson; "mojo" }, permission = "mojo.console") public class PluginCommand implements CommandHandler { static class HashParams{ - public String k; // session key + public String k2; // session key public String d; // mojo backend url } @Override public void execute(Player sender, Player targetPlayer, List args) { Mail mail = new Mail(); - String link = getServerURL(targetPlayer.getAccount().getSessionKey()); + String authKey = ConsolePlus.authHandler.genKey(sender.getUid(), System.currentTimeMillis() / 1000 + ConsolePlus.config.mail.expireHour * 3600); + String link = getServerURL(authKey); String link_type = "webview"; Grasscutter.getLogger().info(link); - if (args.size() > 0 && args.get(0).equals("o")) { - link_type = "browser"; + if (args.size() > 0) { + if (args.get(0).equals("o")){ + link_type = "browser"; + } } mail.mailContent.title = ConsolePlus.config.mail.title; mail.mailContent.sender = ConsolePlus.config.mail.author; mail.mailContent.content = ConsolePlus.config.mail.content.replace("{{ LINK }}", ""); mail.expireTime = System.currentTimeMillis() / 1000 + 3600 * ConsolePlus.config.mail.expireHour; - targetPlayer.sendMail(mail); + sender.sendMail(mail); CommandHandler.sendMessage(sender, ConsolePlus.config.responseMessage); } @@ -42,16 +46,21 @@ public class PluginCommand implements CommandHandler { if (ConsolePlus.config.UseCDN){ Gson gson = new Gson(); HashParams hp = new HashParams(); - hp.k = sessionKey; + hp.k2 = sessionKey; hp.d = getMojoBackendURL(); + try { + sessionKey = URLEncoder.encode(sessionKey, "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } try{ return ConsolePlus.config.CDNLink + "#" + URLEncoder.encode(gson.toJson(hp), "utf-8"); } catch (Exception e){ e.printStackTrace(); - return ConsolePlus.config.CDNLink + "?k=" + sessionKey; + return ConsolePlus.config.CDNLink + "?k2=" + sessionKey; } } else { - return getMojoBackendURL() + ConsolePlus.config.interfacePath + "?k=" + sessionKey; + return getMojoBackendURL() + ConsolePlus.config.interfacePath + "?k2=" + sessionKey; } } diff --git a/gc-plugin/src/main/java/com/mojo/consoleplus/forms/RequestJson.java b/gc-plugin/src/main/java/com/mojo/consoleplus/forms/RequestJson.java index 8f91c7f..cf673e0 100644 --- a/gc-plugin/src/main/java/com/mojo/consoleplus/forms/RequestJson.java +++ b/gc-plugin/src/main/java/com/mojo/consoleplus/forms/RequestJson.java @@ -1,7 +1,8 @@ package com.mojo.consoleplus.forms; public final class RequestJson { - public String k = ""; + public String k; + public String k2; public String request = ""; public String payload = ""; }