Impl new auth method to avoid using sessionKey

This commit is contained in:
mingjun97 2022-05-18 20:33:31 -07:00
parent 57e7ac5436
commit cc0cb2fd81
5 changed files with 119 additions and 34 deletions

View File

@ -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();
}
}

View File

@ -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

View File

@ -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<Integer, Player> 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<Integer, Player> 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));
}
}

View File

@ -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<String> 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 }}", "<type=\""+ link_type + "\" text=\"Mojo Console\" href=\"" + 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;
}
}

View File

@ -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 = "";
}