This commit is contained in:
2025-12-11 18:30:35 +08:00
parent 99937e9feb
commit 8b211fbad6
35 changed files with 527 additions and 302 deletions

View File

@@ -36,7 +36,10 @@
<artifactId>mybatis</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- Spring Boot (用于加密工具) -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -35,13 +35,24 @@ public class AesEncryptUtil {
* 从配置文件读取密钥,如果没有则生成新密钥
*/
public AesEncryptUtil(@Value("${security.aes.secret-key:}") String secretKeyString) {
if (secretKeyString == null || secretKeyString.isEmpty()) {
// 生产环境应该从配置中心或密钥管理系统获取
try {
if (secretKeyString == null || secretKeyString.isEmpty()) {
// 生产环境应该从配置中心或密钥管理系统获取
this.secretKey = generateKey();
System.err.println("警告: 未配置 AES 密钥,使用临时生成的密钥。生产环境请配置 security.aes.secret-key");
} else {
byte[] decodedKey = Base64.getDecoder().decode(secretKeyString);
if (decodedKey.length != 32) {
throw new IllegalArgumentException("AES-256 密钥长度必须是 32 字节,当前: " + decodedKey.length);
}
this.secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM);
System.out.println("✓ AES-256 加密工具初始化成功");
}
} catch (Exception e) {
System.err.println("❌ AES 密钥初始化失败: " + e.getMessage());
// 生成临时密钥以避免启动失败
this.secretKey = generateKey();
System.err.println("警告: 未配置 AES 密钥,使用临时生成的密钥。生产环境请配置 security.aes.secret-key");
} else {
byte[] decodedKey = Base64.getDecoder().decode(secretKeyString);
this.secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM);
System.err.println("已生成临时密钥,请尽快配置正确的 security.aes.secret-key");
}
}
@@ -169,9 +180,32 @@ public class AesEncryptUtil {
}
/**
* 脱敏显示手机号
* 生成手机号Hash用于数据库查询
* 使用SHA-256生成固定Hash相同手机号总是得到相同Hash
*/
public static String maskPhone(String phone) {
if (phone == null || phone.isEmpty()) {
return phone;
}
try {
java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(phone.getBytes(java.nio.charset.StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (Exception e) {
throw new RuntimeException("生成手机号Hash失败", e);
}
}
/**
* 脱敏显示手机号(用于前端显示)
*/
public static String maskPhoneDisplay(String phone) {
if (phone == null || phone.length() < 11) {
return phone;
}
@@ -187,4 +221,26 @@ public class AesEncryptUtil {
}
return idCard.substring(0, 6) + "********" + idCard.substring(14);
}
public static void main(String[] args) {
AesEncryptUtil aesEncryptUtil = new AesEncryptUtil("MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=");
String phone = "17857100375";
// 测试加密(每次都不同,不能用于查询)
String encryptedPhone1 = aesEncryptUtil.encryptPhone(phone);
String encryptedPhone2 = aesEncryptUtil.encryptPhone(phone);
System.out.println("第一次加密: " + encryptedPhone1);
System.out.println("第二次加密: " + encryptedPhone2);
System.out.println("两次加密相同? " + encryptedPhone1.equals(encryptedPhone2));
// 测试Hash用于查询相同手机号总是得到相同Hash
String hash1 = AesEncryptUtil.maskPhone(phone);
String hash2 = AesEncryptUtil.maskPhone(phone);
System.out.println("\n第一次Hash: " + hash1);
System.out.println("第二次Hash: " + hash2);
System.out.println("两次Hash相同? " + hash1.equals(hash2));
// 测试脱敏显示
System.out.println("\n脱敏显示: " + AesEncryptUtil.maskPhoneDisplay(phone));
}
}

View File

@@ -0,0 +1,37 @@
package org.xyzh.common.utils.crypto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import jakarta.annotation.PostConstruct;
/**
* TypeHandler 配置类
* 用于初始化 EncryptedStringTypeHandler 中的 AesEncryptUtil
*
* @author yslg
* @since 2025-12-11
*/
@Configuration
@ConditionalOnClass(AesEncryptUtil.class)
public class TypeHandlerConfig {
private final AesEncryptUtil aesEncryptUtil;
@Autowired(required = false)
public TypeHandlerConfig(AesEncryptUtil aesEncryptUtil) {
this.aesEncryptUtil = aesEncryptUtil;
}
@PostConstruct
public void init() {
// 初始化 TypeHandler 中的静态 AesEncryptUtil 实例
if (aesEncryptUtil != null) {
EncryptedStringTypeHandler.setAesEncryptUtil(aesEncryptUtil);
System.out.println("✓ TypeHandler 已初始化 AES 加密工具");
} else {
System.err.println("警告: AesEncryptUtil 未能注入,加密功能可能无法正常工作");
}
}
}