gateway
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 未能注入,加密功能可能无法正常工作");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user