项目场景:
需要将数据入库时进行加密,查询时对数据进行解密,这里算法使用SM4国密对称算法;
为了使用起来更加优雅,这里使用自定义类型转换器,在实体的属性上注解上指定自定义的类型转换器,便可以自动实现数据的加密解密
代码实现
@Slf4j
@MappedTypes(String.class)
public class EncrpTypeHandler extends BaseTypeHandler<String> {
private static SymmetricCrypto SM4;
/**
* 初始化加密类
*
* @param key 密钥key
* @param iv 加密偏移量
*/
public synchronized static void initEncrypt(String key, String iv) {
if (SM4 == null) {
SM4 = new SM4(CBC, ZeroPadding, key.getBytes(CharsetUtil.CHARSET_UTF_8), iv.getBytes(CharsetUtil.CHARSET_UTF_8));
} else {
throw new IllegalStateException("加密类已经初始化,不允许二次初始化!");
}
}
/**
* 非空字段加密
*
* @param preparedStatement
* @param i
* @param parameter
* @param jdbcType
* @throws SQLException
*/
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, String parameter, JdbcType jdbcType) {
try {
if (StrUtil.isBlank(parameter)) {
return;
}
String encrypt = encrypt(parameter);
preparedStatement.setString(i, encrypt);
} catch (Exception e) {
log.error("typeHandler加密异常:{}", e.getMessage());
}
}
/**
* 非空字段解密 使用列名
*
* @param resultSet
* @param columnName
* @return
* @throws SQLException
*/
@Override
public String getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
String col = resultSet.getString(columnName);
try {
if (StrUtil.isBlank(col)) {
return col;
}
return decrypt(col);
} catch (Exception e) {
log.error("typeHandler解密异常:{}", e.getMessage());
}
return col;
}
/**
* 可空字段解密 使用下标
*
* @param resultSet
* @param columnIndex
* @return
* @throws SQLException
*/
@Override
public String getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
String col = resultSet.getString(columnIndex);
try {
if (StrUtil.isBlank(col)) {
return col;
}
return decrypt(col);
} catch (Exception e) {
log.error("typeHandler解密异常:{}", e.getMessage());
}
return col;
}
/**
* 可空字段解密 存储过程专用
*
* @param callableStatement
* @param columnIndex
* @return
* @throws SQLException
*/
@Override
public String getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
String col = callableStatement.getString(columnIndex);
try {
if (StrUtil.isBlank(col)) {
return col;
}
return decrypt(col);
} catch (Exception e) {
log.error("typeHandler解密异常:{}", e.getMessage());
}
return col;
}
/**
* sm4加密算法
*
* @param plainTxt
* @return
*/
public String encrypt(String plainTxt) {
if (SM4 == null) {
throw new IllegalStateException("加密类未设置密钥!");
}
if (StringUtils.isEmpty(plainTxt)) {
return plainTxt;
}
byte[] encrypHex = SM4.encrypt(plainTxt);
String cipherTxt = Base64.encode(encrypHex);
return cipherTxt;
}
/**
* sm4解密算法
*
* @param cipherTxt
* @return
*/
public String decrypt(String cipherTxt) {
if (SM4 == null) {
throw new IllegalStateException("加密类未设置密钥!");
}
if (StringUtils.isEmpty(cipherTxt)) {
return cipherTxt;
}
byte[] cipherHex = Base64.decode(cipherTxt);
String plainTxt = SM4.decryptStr(cipherHex, CharsetUtil.CHARSET_UTF_8);
return plainTxt;
}
}
@TableField(typeHandler = EncrpTypeHandler.class)
private String password;