From 891f3eb9780ffd698bf326d4f77893d562e8a458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BA=84=E9=94=90=E6=B3=A2?= <10549902+zhuangruibo@user.noreply.gitee.com> Date: Wed, 20 May 2026 21:31:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=A7=E6=B3=95=E7=AB=AF-=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/application-dev-cust-zrb.yml | 6 +- .../test/CustomEncryptorConfigTest.java | 213 ++++++++++++++++++ .../test/JasyptEncryptDecryptTest.java | 112 --------- 3 files changed, 216 insertions(+), 115 deletions(-) create mode 100644 zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/CustomEncryptorConfigTest.java delete mode 100644 zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/JasyptEncryptDecryptTest.java diff --git a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev-cust-zrb.yml b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev-cust-zrb.yml index 28f2ed39..6c11fe63 100644 --- a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev-cust-zrb.yml +++ b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev-cust-zrb.yml @@ -21,9 +21,9 @@ spring: driverClassName: com.mysql.cj.jdbc.Driver # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) - url: ENC(/EKCnamZackeZIip+AZjSAd7HHa1C4Pzh+rEEXWIZbvjWPOyeE+KlbsBDwrU88lXth0/1No6X+xhJahoO7hEpsmZeTpKg/+3r3lzDpUj9zL1rTgjggHLa5T2m3N7mNF0X2gyxe5FlrMOsY7qJ08BdmQ9QZInx5IUZXnRSy0dX7dk18mSNp3VLvTFwsNowW2okMlWtlWCL6tRMb3MvFcmh8CXgiD4oaW2PJ7sYdttAbSl0X71omw2d/XfEmOonPb23waYKuBILlU0lLAkpM9BuqUILcUeiVCZUS9/asP9nZh6+BNT8qkpZkU/4rSsJQUrWsSO5kilXRqTA/PVnTkHlCghxgp2Jgk4DHi8+Mu2sUN7vyW+ZcUiew==) - username: ENC(fe0dFsZDxnT+2WCXoRah3kJLfzX0pc81) - password: ENC(fe0dFsZDxnT+2WCXoRah3kJLfzX0pc81) + url: jdbc:mysql://127.0.0.1:3309/zfjd-refactoring-v3?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: root + password: root --- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉) spring.data: diff --git a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/CustomEncryptorConfigTest.java b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/CustomEncryptorConfigTest.java new file mode 100644 index 00000000..9d2bcb01 --- /dev/null +++ b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/CustomEncryptorConfigTest.java @@ -0,0 +1,213 @@ +package com.zdxt.service.test; + +import org.dromara.common.encrypt.config.jasypt.CustomEncryptorConfig; +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * CustomEncryptorConfig 单元测试 + *

+ * 验证项目自定义 Jasypt 加解密器(PBEWithMD5AndDES + 硬编码密钥 ATPfOhpnAVp6yBas7RU) + * 的加密、解密、幂等性以及异常处理是否符合预期。 + *

+ * + * @author zdxt + */ +@DisplayName("CustomEncryptorConfig 单元测试") +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class CustomEncryptorConfigTest { + + private static CustomEncryptorConfig encryptor; + + @BeforeAll + public static void init() { + encryptor = new CustomEncryptorConfig(); + } + + // ======================== 基础加解密 ======================== + + @Test + @Order(1) + @DisplayName("encrypt - 加密后密文不为空且与原文不同") + public void testEncrypt_producesNonEmptyCiphertext() { + String plainText = "hello_world_123"; + String encrypted = encryptor.encrypt(plainText); + + assertNotNull(encrypted, "密文不应为 null"); + assertFalse(encrypted.isBlank(), "密文不应为空白"); + assertNotEquals(plainText, encrypted, "密文应与原文不同"); + System.out.println("原文: " + plainText + " -> 密文: " + encrypted); + } + + @Test + @Order(2) + @DisplayName("decrypt - 加密后再解密应还原为原文") + public void testDecrypt_restoresOriginalText() { + String plainText = "test_password_zdxt@1234"; + String encrypted = encryptor.encrypt(plainText); + String decrypted = encryptor.decrypt(encrypted); + + assertEquals(plainText, decrypted, "解密结果应与原文一致"); + System.out.println("加解密验证通过: " + plainText + " -> " + encrypted + " -> " + decrypted); + } + + // ======================== 随机盐特性 ======================== + + @Test + @Order(3) + @DisplayName("encrypt - 同一原文多次加密产生不同密文(随机盐)") + public void testEncrypt_randomSaltProducesDifferentCiphertext() { + String plainText = "same_text_for_random_salt"; + + String encrypted1 = encryptor.encrypt(plainText); + String encrypted2 = encryptor.encrypt(plainText); + + assertNotEquals(encrypted1, encrypted2, "随机盐下,同一原文两次加密结果应不同"); + // 但两次密文都能正确解密还原 + assertEquals(plainText, encryptor.decrypt(encrypted1), "第一次密文应能正确解密"); + assertEquals(plainText, encryptor.decrypt(encrypted2), "第二次密文应能正确解密"); + + System.out.println("随机盐验证通过:"); + System.out.println(" 密文1: " + encrypted1); + System.out.println(" 密文2: " + encrypted2); + } + + // ======================== 各种输入类型 ======================== + + @Test + @Order(4) + @DisplayName("encrypt/decrypt - 含特殊字符的字符串") + public void testEncryptDecrypt_specialCharacters() { + String[] testCases = { + "zdxt@1234", + "jdbc:mysql://127.0.0.1:3306/db?useSSL=true&serverTimezone=GMT%2B8", + "p@$$w0rd!#%^&*()", + "中文密码测试", + "mixed_中英文_test_123!" + }; + + for (String plainText : testCases) { + String encrypted = encryptor.encrypt(plainText); + String decrypted = encryptor.decrypt(encrypted); + assertEquals(plainText, decrypted, "特殊字符串加解密应一致: " + plainText); + } + System.out.println("特殊字符加解密验证通过,共 " + testCases.length + " 组"); + } + + @Test + @Order(5) + @DisplayName("encrypt/decrypt - 空字符串") + public void testEncryptDecrypt_emptyString() { + String plainText = ""; + String encrypted = encryptor.encrypt(plainText); + assertNotNull(encrypted, "空字符串加密后密文不应为 null"); + + String decrypted = encryptor.decrypt(encrypted); + assertEquals(plainText, decrypted, "空字符串加解密应一致"); + System.out.println("空字符串加解密验证通过"); + } + + @Test + @Order(6) + @DisplayName("encrypt/decrypt - 超长字符串") + public void testEncryptDecrypt_longString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 100; i++) { + sb.append("LongText_").append(i).append("_"); + } + String plainText = sb.toString(); + + String encrypted = encryptor.encrypt(plainText); + String decrypted = encryptor.decrypt(encrypted); + + assertEquals(plainText, decrypted, "超长字符串加解密应一致"); + System.out.println("超长字符串(长度=" + plainText.length() + ")加解密验证通过"); + } + + // ======================== 异常场景 ======================== + + @Test + @Order(7) + @DisplayName("decrypt - 解密非法密文应抛出异常") + public void testDecrypt_invalidCiphertext() { + assertThrows(Exception.class, () -> encryptor.decrypt("invalid_base64_ciphertext"), + "解密非法密文应抛出异常"); + System.out.println("非法密文解密异常验证通过"); + } + + @Test + @Order(8) + @DisplayName("decrypt - 解密被篡改的密文应抛出异常") + public void testDecrypt_tamperedCiphertext() { + String plainText = "original_text"; + String encrypted = encryptor.encrypt(plainText); + + // 篡改密文(翻转第一个字符) + char first = encrypted.charAt(0); + char tampered = (first == 'A') ? 'B' : 'A'; + String tamperedCiphertext = tampered + encrypted.substring(1); + + // 篡改后的密文解密要么抛异常,要么得到不同的结果 + try { + String result = encryptor.decrypt(tamperedCiphertext); + assertNotEquals(plainText, result, "篡改后的密文不应解密出原文"); + } catch (Exception e) { + // 抛异常也是合理的 + System.out.println("篡改密文解密抛出异常(预期行为): " + e.getClass().getSimpleName()); + } + } + + @Test + @Order(9) + @DisplayName("encrypt - 加密 null 应抛出异常") + public void testEncrypt_nullInput() { + assertThrows(Exception.class, () -> encryptor.encrypt(null), + "加密 null 应抛出异常"); + System.out.println("null 输入加密异常验证通过"); + } + + @Test + @Order(10) + @DisplayName("decrypt - 解密 null 应抛出异常") + public void testDecrypt_nullInput() { + assertThrows(Exception.class, () -> encryptor.decrypt(null), + "解密 null 应抛出异常"); + System.out.println("null 输入解密异常验证通过"); + } + + // ======================== 与已有 ENC 密文兼容性 ======================== + + @Test + @Order(11) + @DisplayName("decrypt - 验证已有配置文件中的 ENC 密文可正常解密") + public void testDecrypt_existingEncValues() { + // application-dev.yml 中的 secretKey 密文 + String encSecretKey = "zTr/tj2VgFxQyunI4eIL7NyRWDPSMPSB0VlwTYeHTdsEWyu1H96xWw=="; + + try { + String decrypted = encryptor.decrypt(encSecretKey); + assertNotNull(decrypted, "配置文件中已有的 ENC 密文应能正常解密"); + assertFalse(decrypted.isBlank(), "解密结果不应为空白"); + System.out.println("已有 ENC 密文解密验证通过,解密结果长度: " + decrypted.length()); + } catch (Exception e) { + fail("配置文件中已有的 ENC 密文解密失败: " + e.getMessage()); + } + } + + // ======================== 一致性验证 ======================== + + @Test + @Order(12) + @DisplayName("encrypt/decrypt - 多次连续加解密结果一致") + public void testEncryptDecrypt_consistency() { + String plainText = "consistency_check_value"; + + for (int i = 0; i < 10; i++) { + String encrypted = encryptor.encrypt(plainText); + String decrypted = encryptor.decrypt(encrypted); + assertEquals(plainText, decrypted, "第 " + (i + 1) + " 次加解密结果不一致"); + } + System.out.println("连续 10 次加解密一致性验证通过"); + } +} diff --git a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/JasyptEncryptDecryptTest.java b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/JasyptEncryptDecryptTest.java deleted file mode 100644 index 97bffc1d..00000000 --- a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/JasyptEncryptDecryptTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.zdxt.service.test; - -import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; -import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig; -import org.junit.jupiter.api.*; - -/** - * Jasypt 加解密测试 - *

- * 与 CustomEncryptorConfig 使用相同的密钥和算法配置, - * 可直接运行获取加密后的密文用于配置文件 ENC(...) 占位。 - *

- * - * @author zdxt - */ -@DisplayName("Jasypt 加解密测试") -public class JasyptEncryptDecryptTest { - - private static final String CRACK = "ATPfOhpnAVp6yBas7RU"; - - private static PooledPBEStringEncryptor encryptor; - - @BeforeAll - public static void init() { - encryptor = new PooledPBEStringEncryptor(); - SimpleStringPBEConfig config = new SimpleStringPBEConfig(); - config.setPassword(CRACK); - config.setAlgorithm("PBEWithMD5AndDES"); - config.setKeyObtentionIterations("1000"); - config.setPoolSize("1"); - config.setProviderName("SunJCE"); - config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator"); - config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator"); - config.setStringOutputType("base64"); - encryptor.setConfig(config); - } - - @DisplayName("加密原文并输出密文") - @Test - public void testEncrypt() { - // ===== 修改此处为需要加密的原文 ===== - String plainText = "jdbc:mysql://localhost:3309/zfjd-refactoring-v3?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true"; - plainText="root"; - - String encrypted = encryptor.encrypt(plainText); - Assertions.assertNotNull(encrypted, "密文不应为 null"); - Assertions.assertFalse(encrypted.isBlank(), "密文不应为空"); - - System.out.println("========== 加密结果 =========="); - System.out.println("原文: " + plainText); - System.out.println("密文: " + encrypted); - System.out.println("配置文件使用: ENC(" + encrypted + ")"); - } - - @DisplayName("加密后解密应还原为原文") - @Test - public void testEncryptAndDecrypt() { - String plainText = "test_encrypt_decrypt_123"; - - String encrypted = encryptor.encrypt(plainText); - String decrypted = encryptor.decrypt(encrypted); - - Assertions.assertEquals(plainText, decrypted, "解密结果应与原文一致"); - System.out.println("加密解密验证通过: " + plainText + " -> " + encrypted + " -> " + decrypted); - } - - @DisplayName("同一原文多次加密应产生不同密文(随机盐)") - @Test - public void testRandomSaltProducesDifferentCiphertext() { - String plainText = "same_plain_text"; - - String encrypted1 = encryptor.encrypt(plainText); - String encrypted2 = encryptor.encrypt(plainText); - - Assertions.assertNotEquals(encrypted1, encrypted2, "随机盐下同一原文两次加密结果应不同"); - // 但两次密文都能正确解密 - Assertions.assertEquals(plainText, encryptor.decrypt(encrypted1)); - Assertions.assertEquals(plainText, encryptor.decrypt(encrypted2)); - System.out.println("随机盐验证通过:"); - System.out.println(" 密文1: " + encrypted1); - System.out.println(" 密文2: " + encrypted2); - } - - @DisplayName("解密错误密文应抛出异常") - @Test - public void testDecryptInvalidCiphertext() { - Assertions.assertThrows(Exception.class, () -> encryptor.decrypt("invalid_ciphertext"), - "解密非法密文应抛出异常"); - System.out.println("非法密文解密异常验证通过"); - } - - @DisplayName("批量加密 - 在此添加需要加密的原文") - @Test - public void testBatchEncrypt() { - // ===== 在此添加需要加密的原文列表 ===== - String[] plainTexts = { - "your_db_password", - "your_redis_password" - }; - - System.out.println("========== 批量加密结果 =========="); - for (String text : plainTexts) { - String encrypted = encryptor.encrypt(text); - System.out.println("原文: " + text); - System.out.println("配置: ENC(" + encrypted + ")"); - System.out.println("-----------------------------------"); - - // 验证可解密 - Assertions.assertEquals(text, encryptor.decrypt(encrypted)); - } - } -}