4 changed files with 115 additions and 8 deletions
-
39src/main/java/com/spring/common/typehandler/EncryptTypeHandler.java
-
66src/main/java/com/spring/common/utils/AesUtils.java
-
4src/main/java/com/spring/modules/sys/entity/SysUserEntity.java
@ -0,0 +1,39 @@ |
|||||
|
package com.spring.common.typehandler; |
||||
|
|
||||
|
import com.spring.common.utils.AesUtils; |
||||
|
import org.apache.ibatis.type.BaseTypeHandler; |
||||
|
import org.apache.ibatis.type.JdbcType; |
||||
|
import org.apache.ibatis.type.MappedTypes; |
||||
|
|
||||
|
import java.sql.CallableStatement; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
|
||||
|
/** |
||||
|
* MyBatis TypeHandler:在 SQL 层面自动加解密字符串字段。 |
||||
|
* 写入数据库时加密,读取时解密,Java 层始终操作明文。 |
||||
|
*/ |
||||
|
@MappedTypes(String.class) |
||||
|
public class EncryptTypeHandler extends BaseTypeHandler<String> { |
||||
|
|
||||
|
@Override |
||||
|
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { |
||||
|
ps.setString(i, AesUtils.encrypt(parameter)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getNullableResult(ResultSet rs, String columnName) throws SQLException { |
||||
|
return AesUtils.decrypt(rs.getString(columnName)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { |
||||
|
return AesUtils.decrypt(rs.getString(columnIndex)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { |
||||
|
return AesUtils.decrypt(cs.getString(columnIndex)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,66 @@ |
|||||
|
package com.spring.common.utils; |
||||
|
|
||||
|
import javax.crypto.Cipher; |
||||
|
import javax.crypto.spec.SecretKeySpec; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
import java.util.Base64; |
||||
|
|
||||
|
/** |
||||
|
* AES对称加密工具类,用于IFS密码等需要可逆加密的场景。 |
||||
|
* 已加密的值以 "ENC:" 前缀标识,保持对旧明文数据的向下兼容。 |
||||
|
*/ |
||||
|
public class AesUtils { |
||||
|
|
||||
|
/** 16字节 = 128位 AES密钥,生产环境建议通过配置文件注入 */ |
||||
|
private static final String AES_KEY = "PLMIfsKey@202501"; |
||||
|
private static final String ALGORITHM = "AES/ECB/PKCS5Padding"; |
||||
|
private static final String ENC_PREFIX = "ENC:"; |
||||
|
|
||||
|
/** |
||||
|
* 加密明文,返回带 ENC: 前缀的密文字符串 |
||||
|
*/ |
||||
|
public static String encrypt(String plaintext) { |
||||
|
if (plaintext == null || plaintext.isEmpty()) { |
||||
|
return plaintext; |
||||
|
} |
||||
|
if (plaintext.startsWith(ENC_PREFIX)) { |
||||
|
return plaintext; |
||||
|
} |
||||
|
try { |
||||
|
SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes(StandardCharsets.UTF_8), "AES"); |
||||
|
Cipher cipher = Cipher.getInstance(ALGORITHM); |
||||
|
cipher.init(Cipher.ENCRYPT_MODE, keySpec); |
||||
|
byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); |
||||
|
return ENC_PREFIX + Base64.getEncoder().encodeToString(encrypted); |
||||
|
} catch (Exception e) { |
||||
|
throw new RuntimeException("AES加密失败", e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 解密带 ENC: 前缀的密文,返回明文。 |
||||
|
* 若值不含前缀(旧明文数据),直接原样返回,保持向下兼容。 |
||||
|
*/ |
||||
|
public static String decrypt(String ciphertext) { |
||||
|
if (ciphertext == null || ciphertext.isEmpty()) { |
||||
|
return ciphertext; |
||||
|
} |
||||
|
if (!ciphertext.startsWith(ENC_PREFIX)) { |
||||
|
return ciphertext; |
||||
|
} |
||||
|
try { |
||||
|
String base64 = ciphertext.substring(ENC_PREFIX.length()); |
||||
|
SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes(StandardCharsets.UTF_8), "AES"); |
||||
|
Cipher cipher = Cipher.getInstance(ALGORITHM); |
||||
|
cipher.init(Cipher.DECRYPT_MODE, keySpec); |
||||
|
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(base64)); |
||||
|
return new String(decrypted, StandardCharsets.UTF_8); |
||||
|
} catch (Exception e) { |
||||
|
throw new RuntimeException("AES解密失败", e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static boolean isEncrypted(String value) { |
||||
|
return value != null && value.startsWith(ENC_PREFIX); |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue