当前位置: 首页 > news >正文

MyBatis学习笔记-数据加密解密

如果需要对一些特殊数据进行加密、解密处理,查阅部分资料文档,一般会避开在复杂的业务层处理,大部分会在数据访问层进行数据的加密、解密处理。目前比较普遍的两种方式如下:
一、基于自定义类型转换器
主要是使用mybatis框架提供的TypeHandler来实现在持久层处理数据。
  • 实现方式
    • 持久化实体对象类中对应字段@TableField注解上新增typeHandler属性配置即可。
    • Mapper映射文件resultMap标签下对应字段result标签新增typeHandler属性配置即可。
  • 注意事项
    • 目前验证支持mybatis框架自带的语句可以生效,部分情况也失效,如查询条件包含需要加密解密的字段。
    • 不支持自定义语句。
@Slf4j
@MappedTypes({String.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class AesEncryptDecryptTypeHandler extends BaseTypeHandler<String> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, AesUtils.encryptToHex(parameter, Constants.AES_SECRET));}@Overridepublic String getNullableResult(ResultSet rs, String columnName) throws SQLException {return decrypt(rs.getString(columnName));}@Overridepublic String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return decrypt(rs.getString(columnIndex));}@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return decrypt(cs.getString(columnIndex));}private String decrypt(String value) {if (null == value || value.length() == 0) {return null ;}try {value = AesUtils.decryptFromHex(value, Constants.AES_SECRET);} catch (Exception e) {log.error(e.getMessage());}return value;}}
二、基于拦截器
主要是使用mybatis框架提供的Interceptor来实现在相关操作过程的数据处理。
  • 实现方式
    • 扩展Interceptor功能,拦截相关操作进行筛选判断实现加密解密。
  • 注意事项
    • 存在多次判断、反射等操作可能存在效率问题。
    • 多种情况还需要单独处理,如查询加密解密字段等。
@Slf4j
@Intercepts({@Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class)})
public class ParameterEncryptInterceptor extends ParameterInterceptor implements Interceptor, InitializingBean {private EncryptDecryptProperties encryptDecryptProperties;private RsaSolver rsaSolver;public ParameterEncryptInterceptor(EncryptDecryptProperties encryptDecryptProperties) {this.encryptDecryptProperties = encryptDecryptProperties;}@Overridepublic void afterPropertiesSet() throws Exception {EncryptDecryptProperties.AlgorithmConfig algorithmConfig = encryptDecryptProperties.getAlgorithmConfig();if (Constants.ALGORITHM_RSA.equalsIgnoreCase(algorithmConfig.getName())) {String rsaBeanName = algorithmConfig.getRsaBeanName();if (CharSequenceUtil.isNotBlank(rsaBeanName) && applicationContext.containsBean(rsaBeanName)) {rsaSolver = applicationContext.getBean(rsaBeanName, RsaSolver.class);}}}@Overridepublic Object intercept(Invocation invocation) throws Throwable {return handleInvocation(invocation);}@Overridepublic Map<String, List<String>> getObjectFieldsMap() {return encryptDecryptProperties.getObjectFieldsMap();}@Overridepublic Object handleObjectField(Object objectFieldValue) {// 暂时只处理字符串类型String objectFieldStringValue = String.valueOf(objectFieldValue);EncryptDecryptProperties.AlgorithmConfig algorithmConfig = encryptDecryptProperties.getAlgorithmConfig();String algorithmName = algorithmConfig.getName().toUpperCase();String algorithmSecret = algorithmConfig.getSecret();switch (algorithmName) {case Constants.ALGORITHM_DES:objectFieldStringValue = DesUtils.encryptBy3DesToHex(objectFieldStringValue, algorithmSecret);break;case Constants.ALGORITHM_AES:objectFieldStringValue = AesUtils.encryptToHex(objectFieldStringValue, algorithmSecret);break;case Constants.ALGORITHM_RSA:objectFieldStringValue = rsaSolver.encrypt(objectFieldStringValue.getBytes(StandardCharsets.UTF_8));break;default:break;}return objectFieldStringValue;}}
@Slf4j
public abstract class ParameterInterceptor extends AbstractInterceptor {/*** handle invocation* @param invocation* @return* @throws Throwable*/protected Object handleInvocation(Invocation invocation) throws Throwable {ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();MetaObject metaObject = MetaObject.forObject(parameterHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());Object parameterObject = parameterHandler.getParameterObject();if (null == parameterObject) {return invocation.proceed();}Class<Object> parameterizedType = getParameterizedType((MappedStatement) metaObject.getValue("mappedStatement"));List<String> fields = getObjectFieldsMap().get(parameterizedType.getName());if (null == fields || fields.isEmpty()) {return invocation.proceed();}if (parameterObject instanceof Map) {Map<String, Object> parameterMapObject = (Map<String, Object>) parameterObject;if (parameterMapObject.containsKey(com.baomidou.mybatisplus.core.toolkit.Constants.ENTITY)) {// handle entity objectObject etObject = parameterMapObject.get(com.baomidou.mybatisplus.core.toolkit.Constants.ENTITY);if (null != etObject) {handleObjectFields(etObject);}} if (parameterMapObject.containsKey(com.baomidou.mybatisplus.core.toolkit.Constants.WRAPPER)) {// handle wrapper objecthandleObjectFields(metaObject, fields);} else {// handle map objecthandleObjectFields(parameterizedType, parameterMapObject);}} else {handleObjectFields(parameterObject);}return invocation.proceed();}}

http://www.mrgr.cn/news/82774.html

相关文章:

  • 【银河麒麟高级服务器操作系统实例】tcp半链接数溢出分析及处理全过程
  • Linux系统的ioremap()函数详解【包含对页对齐地址的详解】
  • OSPF - 影响OSPF邻居建立的因素
  • Zero to JupyterHub with Kubernetes 下篇 - Jupyterhub on k8s
  • 力扣-数组-01两数之和
  • RAG项目推荐:bRAG-langchain-构建自己的 RAG 应用程序所需了解的一切
  • github gitbook写书
  • vue项目上传ofd文件,导致文件类型丢失问题
  • 【C#】C# 使用onnxruntime报错记录
  • 51单片机——步进电机模块
  • 【AI落地】AI生成测试用例,claude or gpt?(提效至少 50%)
  • Linux: 关于 mount 的一些细节
  • STM32 I2C通信外设
  • FreeSWITCH 呼出之我见
  • java常见面试题
  • [备忘.OFD]OFD是什么、OFD与PDF格式文件的互转换
  • 起重机检测数据集VOC+YOLO格式2316张1类别
  • Spring 复习笔记
  • Vue笔记-001-声明式渲染
  • 【简博士统计学习方法】3. 统计学习方法的三要素
  • 自定义字典转换器用于easyExcel 导入导出
  • 51单片机(二)中断系统与外部中断实验
  • INT305 Machine Learning
  • Linux 35.6 + JetPack v5.1.4之 pytorch升级
  • 【LC】2469. 温度转换
  • Haskell语言的面向对象编程