fix(token,AxisInnovatorsBox) 修复报错NullPointerException,添加token持久化加解密逻辑
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
#Current Loaded Language
|
#Current Loaded Language
|
||||||
#Sat Aug 16 18:11:03 CST 2025
|
#Mon Aug 18 02:11:52 CST 2025
|
||||||
loadedLanguage=system\:zh_CN
|
loadedLanguage=system\:zh_CN
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import com.axis.innovators.box.register.RegistrationSettingsItem;
|
|||||||
import com.axis.innovators.box.register.RegistrationTool;
|
import com.axis.innovators.box.register.RegistrationTool;
|
||||||
import com.axis.innovators.box.register.RegistrationTopic;
|
import com.axis.innovators.box.register.RegistrationTopic;
|
||||||
import com.axis.innovators.box.tools.*;
|
import com.axis.innovators.box.tools.*;
|
||||||
|
import com.axis.innovators.box.tools.Crypto.AESCryptoUtil;
|
||||||
|
import com.axis.innovators.box.tools.Crypto.Base64CryptoUtil;
|
||||||
import com.axis.innovators.box.util.PythonResult;
|
import com.axis.innovators.box.util.PythonResult;
|
||||||
import com.axis.innovators.box.util.Tray;
|
import com.axis.innovators.box.util.Tray;
|
||||||
import com.axis.innovators.box.verification.LoginResult;
|
import com.axis.innovators.box.verification.LoginResult;
|
||||||
@@ -94,14 +96,29 @@ public class AxisInnovatorsBox {
|
|||||||
(Exception) throwable : new Exception(throwable));
|
(Exception) throwable : new Exception(throwable));
|
||||||
});
|
});
|
||||||
// 初始化,这里为了能够在登录窗口使用主题,特意将初始化放在构造函数中
|
// 初始化,这里为了能够在登录窗口使用主题,特意将初始化放在构造函数中
|
||||||
main.initLog4j2();
|
initLog4j2();
|
||||||
main.setTopic();
|
setTopic();
|
||||||
// 加载登录信息,如果没有,弹出登录弹窗,后续可以删掉默认弹出
|
// 加载登录信息,如果没有,弹出登录弹窗,后续可以删掉默认弹出
|
||||||
// TODO: login window should not be show when AxisInnovatorsBox initialize,
|
// TODO: login window should not be show when AxisInnovatorsBox initialize,
|
||||||
// it should be show when user click login button.
|
// it should be show when user click login button.
|
||||||
try {
|
try {
|
||||||
StateManager stateManager = new StateManager();
|
StateManager stateManager = new StateManager();
|
||||||
String token = stateManager.getState("loginToken");
|
String excryptedKey = "loginToken";
|
||||||
|
try {
|
||||||
|
excryptedKey = Base64CryptoUtil.base64Encode(excryptedKey);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Failed to encrypt key", e);
|
||||||
|
}
|
||||||
|
String encryptedToken = stateManager.getState(excryptedKey);
|
||||||
|
String token = null;
|
||||||
|
if (encryptedToken != null && !encryptedToken.isEmpty()) {
|
||||||
|
try {
|
||||||
|
token = AESCryptoUtil.decrypt(encryptedToken);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Token 解密失败", ex);
|
||||||
|
token = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (token == null || token.isEmpty()) {
|
if (token == null || token.isEmpty()) {
|
||||||
LoginResult loginResult = CasdoorLoginWindow.showLoginDialogAndGetLoginResult();
|
LoginResult loginResult = CasdoorLoginWindow.showLoginDialogAndGetLoginResult();
|
||||||
if (loginResult == null) {
|
if (loginResult == null) {
|
||||||
@@ -110,7 +127,8 @@ public class AxisInnovatorsBox {
|
|||||||
JOptionPane.INFORMATION_MESSAGE);
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
} else if (loginResult.success()) {
|
} else if (loginResult.success()) {
|
||||||
loginData = loginResult.loginData();
|
loginData = loginResult.loginData();
|
||||||
stateManager.saveState("loginToken", loginResult.token());
|
String encrypted = AESCryptoUtil.encrypt(loginResult.token());
|
||||||
|
stateManager.saveState(excryptedKey, encrypted);
|
||||||
logger.info(
|
logger.info(
|
||||||
"Login result: token: " + loginResult.token() + ", user: " + loginResult.user());
|
"Login result: token: " + loginResult.token() + ", user: " + loginResult.user());
|
||||||
JOptionPane.showMessageDialog(null, "登录成功", "登录",
|
JOptionPane.showMessageDialog(null, "登录成功", "登录",
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.axis.innovators.box.tools.Crypto;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class AESCryptoUtil {
|
||||||
|
private static final String KEY_FILE = System.getProperty("user.home") + "/.lingqi/.axis_box_key";
|
||||||
|
|
||||||
|
// 获取密钥(Base64字符串,长度16字节)
|
||||||
|
public static byte[] getKeyBytes() throws Exception {
|
||||||
|
Path path = Paths.get(KEY_FILE);
|
||||||
|
if (Files.exists(path)) {
|
||||||
|
byte[] encrypted = Base64.getDecoder().decode(Files.readAllBytes(path));
|
||||||
|
return WindowsDPAPIUtil.unprotect(encrypted);
|
||||||
|
} else {
|
||||||
|
// 首次生成密钥
|
||||||
|
byte[] keyBytes = new byte[16];
|
||||||
|
new SecureRandom().nextBytes(keyBytes);
|
||||||
|
byte[] encrypted = WindowsDPAPIUtil.protect(keyBytes);
|
||||||
|
Files.createDirectories(path.getParent());
|
||||||
|
Files.write(path, Base64.getEncoder().encode(encrypted));
|
||||||
|
return keyBytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加密
|
||||||
|
public static String encrypt(String data) throws Exception {
|
||||||
|
byte[] keyBytes = getKeyBytes();
|
||||||
|
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
|
||||||
|
Cipher cipher = Cipher.getInstance("AES");
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
|
||||||
|
byte[] encrypted = cipher.doFinal(data.getBytes("UTF-8"));
|
||||||
|
return Base64.getEncoder().encodeToString(encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解密
|
||||||
|
public static String decrypt(String encrypted) throws Exception {
|
||||||
|
byte[] keyBytes = getKeyBytes();
|
||||||
|
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
|
||||||
|
Cipher cipher = Cipher.getInstance("AES");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, keySpec);
|
||||||
|
byte[] decoded = Base64.getDecoder().decode(encrypted);
|
||||||
|
byte[] decrypted = cipher.doFinal(decoded);
|
||||||
|
return new String(decrypted, "UTF-8");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.axis.innovators.box.tools.Crypto;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class Base64CryptoUtil {
|
||||||
|
|
||||||
|
public static String base64Encode(String input) {
|
||||||
|
return Base64.getEncoder().encodeToString(input.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String base64Decode(String input) {
|
||||||
|
byte[] decodedBytes = Base64.getDecoder().decode(input);
|
||||||
|
return new String(decodedBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.axis.innovators.box.tools.Crypto;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class HashUtil {
|
||||||
|
public static String sha256(String input) throws Exception {
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] hash = digest.digest(input.getBytes("UTF-8"));
|
||||||
|
return Base64.getEncoder().encodeToString(hash); // 输出为Base64字符串
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.axis.innovators.box.tools.Crypto;
|
||||||
|
|
||||||
|
import com.sun.jna.platform.win32.Crypt32Util;
|
||||||
|
|
||||||
|
public class WindowsDPAPIUtil {
|
||||||
|
// 加密
|
||||||
|
public static byte[] protect(byte[] data) {
|
||||||
|
return Crypt32Util.cryptProtectData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解密
|
||||||
|
public static byte[] unprotect(byte[] encrypted) {
|
||||||
|
return Crypt32Util.cryptUnprotectData(encrypted);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user