From e99dcf16787af69c69d16afcd92b6bf8922eede1 Mon Sep 17 00:00:00 2001 From: seatonwan9 Date: 星期四, 28 八月 2025 17:25:24 +0800 Subject: [PATCH] 更新代码 --- src/main/java/com/webmanage/config/EncryptedPropertyEnvironmentPostProcessor.java | 55 +++++++++++ src/main/resources/META-INF/spring.factories | 2 src/main/resources/application-dev.yml | 2 src/main/resources/application-prod.yml | 70 ++++++++++++++ src/main/resources/META-INF/spring/org.springframework.boot.env.EnvironmentPostProcessor | 3 src/main/java/com/webmanage/config/EncryptedPropertyDetector.java | 24 ++++ src/main/java/com/webmanage/util/AESUtil.java | 136 +++++++++++++++++++++++++++ 7 files changed, 291 insertions(+), 1 deletions(-) diff --git a/src/main/java/com/webmanage/config/EncryptedPropertyDetector.java b/src/main/java/com/webmanage/config/EncryptedPropertyDetector.java new file mode 100644 index 0000000..782adea --- /dev/null +++ b/src/main/java/com/webmanage/config/EncryptedPropertyDetector.java @@ -0,0 +1,24 @@ +package com.webmanage.config; + +import org.springframework.util.StringUtils; + +/** + * 妫�娴嬮厤缃�兼槸鍚︿负鍔犲瘑鏍煎紡鐨勫伐鍏� + */ +public class EncryptedPropertyDetector { + + private static final String PREFIX = "AES:"; + + public static boolean isEncrypted(String value) { + return StringUtils.hasText(value) && value.startsWith(PREFIX); + } + + public static String stripPrefix(String value) { + if (!isEncrypted(value)) { + return value; + } + return value.substring(PREFIX.length()); + } +} + + diff --git a/src/main/java/com/webmanage/config/EncryptedPropertyEnvironmentPostProcessor.java b/src/main/java/com/webmanage/config/EncryptedPropertyEnvironmentPostProcessor.java new file mode 100644 index 0000000..6bb4d00 --- /dev/null +++ b/src/main/java/com/webmanage/config/EncryptedPropertyEnvironmentPostProcessor.java @@ -0,0 +1,55 @@ +package com.webmanage.config; + +import com.webmanage.util.AESUtil; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +/** + * 鍦ㄥ簲鐢ㄥ惎鍔ㄦ棭鏈熷鏁忔劅閰嶇疆杩涜瑙e瘑 + */ +public class EncryptedPropertyEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + Map<String, Object> overrides = new HashMap<>(); + // 鎵弿鎵�鏈夊彲鏋氫妇灞炴�ф簮锛屾敹闆嗕互 AES: 寮�澶寸殑灞炴�у�煎苟瑙e瘑锛屾斁鍏ユ渶楂樹紭鍏堢骇瑕嗙洊婧� + for (org.springframework.core.env.PropertySource<?> ps : environment.getPropertySources()) { + if (ps instanceof EnumerablePropertySource) { + EnumerablePropertySource<?> eps = (EnumerablePropertySource<?>) ps; + for (String name : eps.getPropertyNames()) { + Object raw = eps.getProperty(name); + if (raw instanceof String) { + String value = (String) raw; + if (EncryptedPropertyDetector.isEncrypted(value)) { + String cipher = EncryptedPropertyDetector.stripPrefix(value); + String plain = AESUtil.decryptWithDefaultKey(cipher); + overrides.put(name, plain); + } + } + } + } + } + if (!overrides.isEmpty()) { + MutablePropertySources sources = environment.getPropertySources(); + sources.addFirst(new MapPropertySource("decryptedSensitiveProperties", overrides)); + } + } + + // 纭繚灏芥棭鎵ц + @Override + public int getOrder() { + // 鍦ㄩ厤缃枃浠跺姞杞藉畬鎴愬悗鎵ц锛岄伩鍏嶆嬁涓嶅埌鍊� + return Ordered.LOWEST_PRECEDENCE; + } +} + + diff --git a/src/main/java/com/webmanage/util/AESUtil.java b/src/main/java/com/webmanage/util/AESUtil.java new file mode 100644 index 0000000..3bd38e4 --- /dev/null +++ b/src/main/java/com/webmanage/util/AESUtil.java @@ -0,0 +1,136 @@ +package com.webmanage.util; + +import com.webmanage.common.BusinessException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import javax.crypto.Cipher; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +/** + * AES鍔犲瘑宸ュ叿绫� + * + * @author August + * @date 2022-07-29 + */ +@Slf4j +public class AESUtil { + + private AESUtil() { + } + + /** + * AES_KEY + */ + private static final String AES_KEY = "sD6i0YYW1a5FnzF6vRf13VtHocZabRcI"; + + /** + * GCM_IV + */ + private static final String GCM_IV = "1SzB4YR0c0E9"; + + /** + * GCM_TAG闀垮害 + */ + private static final int GCM_TAG_LENGTH = 16; + + /** + * 鍔犲瘑 + * + * @param plaintext 寰呭姞瀵嗘枃鏈� + * @param key AES_KEY + * @param iv GCM_IV + * @return 瀵嗘枃 + */ + public static String encrypt(String plaintext, byte[] key, byte[] iv) { + if (StringUtils.isBlank(plaintext) || key == null || iv == null) { + throw new BusinessException("鍔犲瘑鍙傛暟涓嶈兘涓虹┖"); + } + + try { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv); + + cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec); + + // Perform Encryption + byte[] cipherText = cipher.doFinal(plaintext.getBytes()); + StringBuilder sb = new StringBuilder(); + for (byte b : cipherText) { + String hex = Integer.toHexString(b & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + sb.append(hex); + } + return sb.toString(); + } catch (Exception e) { + throw new BusinessException("鍔犲瘑澶辫触"); + } + } + + /** + * 瑙e瘑 + * + * @param cipherText 瀵嗘枃 + * @param key AES_KEY + * @param iv GCM_IV + * @return 瑙e瘑缁撴灉 + */ + public static String decrypt(String cipherText, byte[] key, byte[] iv) { + if (StringUtils.isBlank(cipherText) || key == null || iv == null) { + throw new BusinessException("瑙e瘑鍙傛暟涓嶈兘涓虹┖"); + } + + try { + byte[] cipherTextByte = new byte[cipherText.length() / 2]; + for (int i = 0; i < cipherText.length() / 2; i++) { + int high = Integer.parseInt(cipherText.substring(i * 2, i * 2 + 1), + 16); + int low = Integer.parseInt( + cipherText.substring(i * 2 + 1, i * 2 + 2), 16); + cipherTextByte[i] = (byte) (high * 16 + low); + } + + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv); + + cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec); + + byte[] decryptedText = cipher.doFinal(cipherTextByte); + + return new String(decryptedText); + } catch (Exception e) { + throw new BusinessException("瑙e瘑澶辫触"); + } + } + + /** + * 浣跨敤榛樿瀵嗛挜鍜孖V杩涜瑙e瘑 + * @param cipherText 浠ュ崄鍏繘鍒跺瓧绗︿覆琛ㄧず鐨勫瘑鏂� + * @return 鏄庢枃 + */ + public static String decryptWithDefaultKey(String cipherText) { + return decrypt(cipherText, AES_KEY.getBytes(), GCM_IV.getBytes()); + } + + public static void main(String[] args) { + // String plainText = "zynlpt2024"; + String plainText = "postgres"; + + log.info("Original Text : " + plainText); + + String cipherText = encrypt(plainText, AES_KEY.getBytes(), GCM_IV.getBytes()); + log.info("Encrypted Text : " + cipherText); + + String decryptedText = decrypt(cipherText, AES_KEY.getBytes(), GCM_IV.getBytes()); + log.info("DeCrypted Text : " + decryptedText); + } +} diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..af6e0fd --- /dev/null +++ b/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.env.EnvironmentPostProcessor=\ +com.webmanage.config.EncryptedPropertyEnvironmentPostProcessor \ No newline at end of file diff --git a/src/main/resources/META-INF/spring/org.springframework.boot.env.EnvironmentPostProcessor b/src/main/resources/META-INF/spring/org.springframework.boot.env.EnvironmentPostProcessor new file mode 100644 index 0000000..595ecdd --- /dev/null +++ b/src/main/resources/META-INF/spring/org.springframework.boot.env.EnvironmentPostProcessor @@ -0,0 +1,3 @@ +com.webmanage.config.EncryptedPropertyEnvironmentPostProcessor + + diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index effd90b..7981842 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -5,7 +5,7 @@ driver-class-name: org.postgresql.Driver url: jdbc:postgresql://localhost:5432/web_manage?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: postgres - password: zkyxpostgres + password: AES:d9d2d3e0d586e76d02a97c451f3256bffdc806b4c7626904 druid: # 鍒濆杩炴帴鏁� initial-size: 5 diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..7581c4d --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,70 @@ + # 鏁版嵁婧愰厤缃� +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: org.postgresql.Driver + url: jdbc:postgresql://192.168.20.52:5432/zypt-v2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: postgres + password: AES:f9d2d3e0d586e76d14aba9d24666acef98c4605be9ec680ac4cbeede7ad2 + druid: + # 鍒濆杩炴帴鏁� + initial-size: 5 + # 鏈�灏忚繛鎺ユ睜鏁伴噺 + min-idle: 10 + # 鏈�澶ц繛鎺ユ睜鏁伴噺 + max-active: 20 + # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂� + max-wait: 60000 + # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣 + time-between-eviction-runs-millis: 60000 + # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣 + min-evictable-idle-time-millis: 300000 + # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣 + max-evictable-idle-time-millis: 900000 + # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁� + validation-query: SELECT 1 + test-while-idle: true + test-on-borrow: false + test-on-return: false + # 鎵撳紑PSCache锛屽苟涓旀寚瀹氭瘡涓繛鎺ヤ笂PSCache鐨勫ぇ灏� + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + # 閰嶇疆鐩戞帶缁熻鎷︽埅鐨刦ilters锛屽幓鎺夊悗鐩戞帶鐣岄潰sql鏃犳硶缁熻锛�'wall'鐢ㄤ簬闃茬伀澧� + filters: stat,wall,slf4j + # 閫氳繃connectProperties灞炴�ф潵鎵撳紑mergeSql鍔熻兘锛涙參SQL璁板綍 + connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + # 閰嶇疆DruidStatFilter + web-stat-filter: + enabled: true + url-pattern: /* + exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" + # 閰嶇疆DruidStatViewServlet + stat-view-servlet: + enabled: true + url-pattern: /druid/* + reset-enable: false + login-username: admin + login-password: 123456 + + # Redis閰嶇疆 + redis: + host: 192.168.20.51 + port: 6379 + password: AES:c8d9cdfddcb4b32c677d657d2c8d56f9e7e4720832656637f5 + database: 4 + timeout: 10000ms + lettuce: + pool: + max-active: 8 + max-wait: -1ms + max-idle: 8 + min-idle: 0 +# MinIO閰嶇疆 +minio: + endpoint: http://192.168.20.52:9000 + access-key: minioadmin + secret-key: AES:c4d4cefddd95e6733df755af0e29839c104ee8baa55eb53cdc24 + part-size: 104857600 + bucket-name: dev + + -- Gitblit v1.8.0