refactor: 配置刷新优化和加密功能移除
- refactor(springboot2): 简化配置刷新逻辑,移除 EnvironmentChangeEvent 包装 - ConfigChangeHanlder 直接接收 Map<String,String> 参数 - 移除 EnvironmentChangeEvent 事件类 - 优化 token 参数构建和敏感信息脱敏处理 - refactor(server): 移除配置加密功能 - 删除 CryptoConfig 结构体和相关配置项 - 移除 application-dev.properties 中的加密配置 - 项目不再使用配置加密功能 - docs: 更新 README 和模块文档 - fix: 修复 Node.js 客户端配置缓存
This commit is contained in:
@@ -64,7 +64,6 @@ database.user=root
|
||||
database.password=your_password
|
||||
jwt.secret=your-jwt-secret
|
||||
jwt.expireHours=24
|
||||
crypto.secretKey=your-crypto-key
|
||||
```
|
||||
|
||||
启动服务(首次启动自动建表并初始化默认数据):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"crypto.secretKey": "k9#mP2$vL7qR4xN8",
|
||||
"database.host": "127.0.0.1",
|
||||
"database.name": "kenaito_conf",
|
||||
"database.password": "1234567",
|
||||
|
||||
+1
-1
@@ -4,5 +4,5 @@ import java.util.Map;
|
||||
|
||||
public interface ConfigChangeHanlder {
|
||||
|
||||
public void onConfigChanged(Map<String, Object> changedConfigs);
|
||||
void onConfigChanged(Map<String, Object> changedConfigs);
|
||||
}
|
||||
|
||||
+27
-117
@@ -7,12 +7,6 @@ import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.slf4j.Logger;
|
||||
@@ -141,67 +135,6 @@ public class ConfigcenterContext {
|
||||
return null;
|
||||
}
|
||||
|
||||
// ==================== Crypto Utils (replaces mendmix AES/DES/Base64/DigestUtils) ====================
|
||||
|
||||
public static String md5(String input) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : digest) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("MD5 error", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String md5Short(String input) {
|
||||
if (input == null || input.isEmpty()) return "";
|
||||
return md5(input).substring(0, 16);
|
||||
}
|
||||
|
||||
private static String desEncrypt(String key, String data) {
|
||||
try {
|
||||
SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "DES");
|
||||
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||
return Base64.getEncoder().encodeToString(encrypted);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("DES encrypt error", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] aesDecrypt(byte[] data, byte[] key) throws Exception {
|
||||
SecretKey secretKey = new SecretKeySpec(key, "AES");
|
||||
// Use CBC mode with zero IV to match Go server
|
||||
IvParameterSpec iv = new IvParameterSpec(new byte[16]);
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
|
||||
byte[] decrypted = cipher.doFinal(data);
|
||||
// Remove PKCS7 padding
|
||||
int padding = decrypted[decrypted.length - 1] & 0xFF;
|
||||
if (padding > 0 && padding <= 16) {
|
||||
byte[] result = new byte[decrypted.length - padding];
|
||||
System.arraycopy(decrypted, 0, result, 0, result.length);
|
||||
return result;
|
||||
}
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
private static String decryptWithAES(String key, String data) {
|
||||
try {
|
||||
String secretKey = md5(key).substring(16);
|
||||
byte[] encrypted = Base64.getDecoder().decode(data.getBytes(StandardCharsets.UTF_8));
|
||||
byte[] decrypted = aesDecrypt(encrypted, secretKey.getBytes(StandardCharsets.UTF_8));
|
||||
return new String(decrypted, StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(String.format("解密错误:%s", data));
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== HTTP Utils (replaces mendmix HttpUtils) ====================
|
||||
|
||||
public static String httpGet(String url) throws Exception {
|
||||
@@ -242,8 +175,7 @@ public class ConfigcenterContext {
|
||||
syncIntervalSeconds = getInt("kenaito.config.sync-interval-seconds", 60);
|
||||
token = getProperty("kenaito.config.token");
|
||||
|
||||
logger.info("\n=====Configcenter config=====\nappName:{}\nenv:{}\nversion:{}\nremoteEnabled:{}\napiBaseUrls:{}\n=====Configcenter config=====",
|
||||
app, env, version, isRemoteEnabled(), JSON.toJSONString(apiBaseUrls));
|
||||
logger.info("\n=====Configcenter config=====\nappName:{}\nenv:{}\nversion:{}\nremoteEnabled:{}\napiBaseUrls:{}\n=====Configcenter config=====", app, env, version, isRemoteEnabled(), JSON.toJSONString(apiBaseUrls));
|
||||
}
|
||||
|
||||
public boolean isRemoteEnabled() {
|
||||
@@ -271,15 +203,29 @@ public class ConfigcenterContext {
|
||||
}
|
||||
}
|
||||
|
||||
public String getApp() { return app; }
|
||||
public String getEnv() { return env; }
|
||||
public String getVersion() { return version; }
|
||||
public boolean isIgnoreGlobal() { return ignoreGlobal; }
|
||||
public String getSecret() { return secret; }
|
||||
public boolean isRemoteFirst() { return remoteFirst; }
|
||||
public int getSyncIntervalSeconds() { return syncIntervalSeconds; }
|
||||
public String getNodeId() { return nodeId; }
|
||||
public boolean isSpringboot() { return isSpringboot; }
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public String getEnv() {
|
||||
return env;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public boolean isIgnoreGlobal() {
|
||||
return ignoreGlobal;
|
||||
}
|
||||
|
||||
public boolean isRemoteFirst() {
|
||||
return remoteFirst;
|
||||
}
|
||||
|
||||
public int getSyncIntervalSeconds() {
|
||||
return syncIntervalSeconds;
|
||||
}
|
||||
|
||||
public void mergeRemoteProperties(Properties properties) {
|
||||
if (!remoteEnabled) return;
|
||||
@@ -343,7 +289,7 @@ public class ConfigcenterContext {
|
||||
|
||||
Set<String> keys = map.keySet();
|
||||
for (String key : keys) {
|
||||
Object value = decodeEncryptIfRequire(map.get(key));
|
||||
Object value = map.get(key);
|
||||
properties.put(key, value);
|
||||
}
|
||||
|
||||
@@ -412,7 +358,7 @@ public class ConfigcenterContext {
|
||||
Set<String> keySet = updateConfig.keySet();
|
||||
for (String key : keySet) {
|
||||
String oldValue = getProperty(key);
|
||||
addProperty(key, decodeEncryptIfRequire(updateConfig.get(key)).toString());
|
||||
addProperty(key, updateConfig.get(key).toString());
|
||||
logger.info("Config [{}] Change, oldValue:{}, newValue:{}", key, oldValue, updateConfig.get(key));
|
||||
}
|
||||
|
||||
@@ -494,8 +440,7 @@ public class ConfigcenterContext {
|
||||
|
||||
// 刷新
|
||||
registry.refresh();
|
||||
logger.info("[RefreshScope] RefreshScopeRegistry.refresh() completed, refreshed {} @Value fields and {} @ConfigurationProperties beans",
|
||||
registry.getValueFieldCount(), registry.getConfigPropsCount());
|
||||
logger.info("[RefreshScope] RefreshScopeRegistry.refresh() completed, refreshed {} @Value fields and {} @ConfigurationProperties beans", registry.getValueFieldCount(), registry.getConfigPropsCount());
|
||||
} catch (Exception e) {
|
||||
logger.warn("[RefreshScope] RefreshScopeRegistry.refresh() error, msg:{}", e.getMessage(), e);
|
||||
}
|
||||
@@ -504,21 +449,6 @@ public class ConfigcenterContext {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean pingCcServer(String pingUrl, int retry) {
|
||||
boolean result = false;
|
||||
try {
|
||||
result = httpGet(pingUrl) != null;
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
if (retry == 0) return false;
|
||||
if (!result) {
|
||||
try { Thread.sleep(1500); } catch (Exception e) { }
|
||||
return pingCcServer(pingUrl, --retry);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String buildTokenParameter(String url) {
|
||||
if (token == null || token.isEmpty()) {
|
||||
return url;
|
||||
@@ -532,26 +462,6 @@ public class ConfigcenterContext {
|
||||
}
|
||||
}
|
||||
|
||||
private Object decodeEncryptIfRequire(Object data) {
|
||||
if (data == null) return "";
|
||||
if (data.toString().startsWith(CRYPT_PREFIX)) {
|
||||
Validate.notBlank(secret, "config[kenaito.config.encrypt-secret] is required");
|
||||
data = data.toString().replace(CRYPT_PREFIX, "");
|
||||
String decryptString;
|
||||
try {
|
||||
decryptString = decryptWithAES(secret, data.toString());
|
||||
} catch (Exception e) {
|
||||
if (globalSecret != null && !globalSecret.isEmpty()) {
|
||||
decryptString = decryptWithAES(globalSecret, data.toString());
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return decryptString;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private String hideSensitive(String key, String origin) {
|
||||
if (StringUtils.isAnyBlank(key, origin)) return "";
|
||||
boolean isSensitive = false;
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
package cn.odboy.confcenter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
public class EnvironmentChangeEvent extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Set<String> keys;
|
||||
|
||||
public EnvironmentChangeEvent(Set<String> keys) {
|
||||
super(keys);
|
||||
this.keys = keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the keys
|
||||
*/
|
||||
public Set<String> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ type Config struct {
|
||||
Server ServerConfig
|
||||
Database DatabaseConfig
|
||||
JWT JWTConfig
|
||||
Crypto CryptoConfig
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
@@ -35,10 +34,6 @@ type JWTConfig struct {
|
||||
ExpireHours int
|
||||
}
|
||||
|
||||
type CryptoConfig struct {
|
||||
SecretKey string
|
||||
}
|
||||
|
||||
var Cfg *Config
|
||||
|
||||
func Load(path string) error {
|
||||
@@ -77,8 +72,6 @@ func Load(path string) error {
|
||||
Cfg.JWT.Secret = baseProps["jwt.secret"]
|
||||
Cfg.JWT.ExpireHours = intProp(baseProps, "jwt.expireHours", 24)
|
||||
|
||||
Cfg.Crypto.SecretKey = baseProps["crypto.secretKey"]
|
||||
|
||||
if Cfg.Database.Host == "" {
|
||||
return fmt.Errorf("missing required config: database.host")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user