前面的一篇文章中写了敏感数据加解密的通用解决方案,这篇文章来写一下具体的业务如何接入这个方案,业务的接入首要宗旨当然是对业务侵入性要最小,尽可能不影响原生的业务逻辑,说白了就是少改点代码。下面给大家提供一个简单的示例和思路
内存->数据库
定义一个注解
/*** description: 加密字段** @author luhui* @date 2023/10/23 18:25*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Encryption {
}
包含敏感字段的实体类增加注解
@Encryption
@ApiModelProperty("联系方式")
private String phone;
重写jpa的save方法,统一拦截方式有多种,如果用的其他框架也可以做相应的切面拦截
@SneakyThrows
@Override
@Transactional(rollbackFor = Exception.class)
public <S extends T> S save(S entity) {Field[] fields = entity.getClass().getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(Encryption.class)) {// 敏感数据加密存储field.setAccessible(true);Object encryptionValue = field.get(entity);if(encryptionValue == null){continue;}field.set(entity, KMSUtil.envelopeEncrypt(encryptionValue.toString()));}}return super.save(entity);
}
数据库->内存
因为我这里的敏感数据查询都是用es索引,所以没有相关应用场景;
如果有的话建议针对有敏感字段的类写一个包含解密的通用查询方法而不是重写get,以免造成明文数据被意外持久化
在阿里巴巴编码规约中,也是不建议重写实体类的set和get,以保证这两个方法的基础用法;
数据库->索引
这个没什么好说的,和以前一样保持一致即可
索引->内存
我这里的索引的查询是基于json封装的,所以不好从实体类入手;
如果是从实体类的话,会更优雅一些,但是对es这种灵活的使用场景来说实体类在业务上使用起来并不是很方便。
可以重载一个包含敏感字段解密流程的search
/*** description: 字段解密处理** @author luhui* @date 2023/10/24 10:56*/
private void decryptionHandler(JSONObject result, JSONArray encryptionFieldNames) {if (Constants.CODE_FAIL.equals(result.getString(Constants.RESULT_CODE))) {return;}JSONArray resultData = result.getJSONObject(Constants.RESULT_DATA).getJSONArray("result");if (resultData.size() == 0) {return;}for (Object fieldName : encryptionFieldNames) {for (Object resultDatum : resultData) {JSONObject data = (JSONObject) resultDatum;String ciphertext = data.getString(fieldName.toString());if (StringUtils.isBlank(ciphertext)) {continue;}// 解密data.put(fieldName.toString(), KMSUtil.envelopeDecrypt(ciphertext));}}
}