mybatis各种查询 Plugins入库字段数据加密查询解密

INSERT INTO `ry`.`sys_user`(`user_id`, `dept_id`, `login_name`, `user_name`, `user_type`, `email`, `phonenumber`, `sex`, `avatar`, `password`, `salt`, `status`, `del_flag`, `login_ip`, `login_date`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1, 103, 'admin', 'eHl4', '00', 'ry@163.com', '15888888888', '1', '', '29c67a30398638269fe600f73a054934', '111111', '0', '0', '127.0.0.1', '2024-02-28 17:49:51', 'admin', '2018-03-16 11:33:00', 'ry', '2024-02-28 17:49:51', '管理员');
INSERT INTO `ry`.`sys_user`(`user_id`, `dept_id`, `login_name`, `user_name`, `user_type`, `email`, `phonenumber`, `sex`, `avatar`, `password`, `salt`, `status`, `del_flag`, `login_ip`, `login_date`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (2, 105, 'ry', 'eHl4', '00', 'ry@qq.com', '15666666666', '1', '', '8e6d98b90472783cc73c17047ddccf36', '222222', '0', '0', '127.0.0.1', '2018-03-16 11:33:00', 'admin', '2018-03-16 11:33:00', 'ry', '2018-03-16 11:33:00', '测试员');

数据库该字段数据配置好base64加密的数据或者先注释掉DecryptionTypeHandler方便测试
配置注册插件二选一。

mybatis:
  configuration:
    plugins:
      - com.example.EncryptionPlugin
      
@Configuration
public class MyBatisConfig{
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
{
    String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
    String mapperLocations = env.getProperty("mybatis.mapperLocations");
    String configLocation = env.getProperty("mybatis.configLocation");
    typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
    VFS.addImplClass(SpringBootVFS.class);

    final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    sessionFactory.setDataSource(dataSource);
    sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
    sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
    sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
    // 注册插件
    sessionFactory.setPlugins(new Interceptor[]{new EncryptionPlugin()});
    return sessionFactory.getObject();
  }
}

拦截执行sql

import java.nio.charset.StandardCharsets;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Base64;
import java.util.Properties;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import com.ruoyi.framework.aspectj.lang.annotation.EncryptedField;
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})
public class EncryptionPlugin  implements Interceptor {

	// @Autowired
	// private EncryptionService encryptionService;

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		Object target = invocation.getTarget();
		if (target instanceof Executor) {
			MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
			System.out.println(ms);
			Object parameter = invocation.getArgs()[1];

			// 插入或更新操作时,加密字段
			MetaObject metaParam = SystemMetaObject.forObject(parameter);
			Class<?> paramClass = parameter.getClass();
			Arrays.stream(paramClass.getDeclaredFields())
					.filter(field -> field.isAnnotationPresent(EncryptedField.class)).forEach(field -> {
						field.setAccessible(true);
						String originalValue = (String) metaParam.getValue(field.getName());
						if (originalValue != null) {
							EncryptedField annotation = field.getAnnotation(EncryptedField.class);
							System.out.println(annotation.value());
							switch (annotation.value()) {
		                     case USER_NAME: 
		                    	 //base64加密
		                    	 String encrypted = Base64.getEncoder().encodeToString(originalValue.getBytes(StandardCharsets.UTF_8));
								 //解密base64 
		                    	 //new String(Base64.getDecoder().decode("eHl4"), StandardCharsets.UTF_8)
		                    	 metaParam.setValue(field.getName(), encrypted);
		                         break;
		                   }	
						}
					});
		} else if (target instanceof ResultSetHandler) {
//		        Statement stmt = (Statement) invocation.getArgs()[0];
//		        // 获取结果集
//		        ResultSet rs = stmt.getResultSet();
//		        // 假设我们知道哪些列需要解密
//		        while (rs.next()) {
//		            // 获取列名
//		            ResultSetMetaData metaData = rs.getMetaData();
//		            for (int i = 1; i <= metaData.getColumnCount(); i++) {
//		                String columnName = metaData.getColumnName(i);
//	                    String encryptedValue = rs.getString(columnName);
//		                System.out.println(columnName+"\t"+encryptedValue);
// 			        	rs.updateString(columnName, decryptedValue);
//
//		        }
//			}
		}
		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
	}
}

字段注解以及使用

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface EncryptedField {

	Types value() default Types.DEFAULT;

	enum Types {
		PHONE_NUMBER, ID_CARD, DEFAULT,USER_NAME
	}
}

@EncryptedField(Types.USER_NAME)
private String userName;

上述字段解密

//配置加载转换器在MyBatisConfig中
@Bean
public TypeHandlerRegistry typeHandlerRegistry() {
    TypeHandlerRegistry registry = new TypeHandlerRegistry();
    registry.register(String.class, DecryptionTypeHandler.class);
    return registry;
}

这里通过mapper.xml配置拦截的字段

<resultMap type="User" id="UserResult">
		<id     property="userId"       column="user_id"      />
		<result property="deptId"       column="dept_id"      />
		<result property="userName"     column="user_name"    typeHandler="com.ruoyi.framework.config.DecryptionTypeHandler" />
</resultMap>

解密转换器

import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Base64;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
//针对user_name解密。如果多个字段那就要配置多个BaseTypeHandler
public class DecryptionTypeHandler extends  BaseTypeHandler<String> {
    //@Autowired
	//private EncryptionService encryptionService;

    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        // 在这里实现加密逻辑
        String encryptedValue = Base64.getEncoder().encodeToString(parameter.getBytes(StandardCharsets.UTF_8));
        ps.setString(i, encryptedValue);
    }

    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 在这里实现解密逻辑
        String encryptedValue = rs.getString(columnName);
        return new String(Base64.getDecoder().decode(encryptedValue), StandardCharsets.UTF_8);
    }

    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // 在这里实现解密逻辑
        String encryptedValue = rs.getString(columnIndex);
        return new String(Base64.getDecoder().decode(encryptedValue), StandardCharsets.UTF_8);
    }

    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        // 在这里实现解密逻辑
        String encryptedValue = cs.getString(columnIndex);
        return new String(Base64.getDecoder().decode(encryptedValue), StandardCharsets.UTF_8);
    }
}

批量更新对每行数据通过连接多个id

<mapper namespace="com.example.mapper.PersonMapper">
   <update id="batchUpdate">
        UPDATE person
        SET name = CASE
       <foreach collection="list" item="person" separator=" ">
            WHEN id = #{person.id} THEN CONCAT_WS(' ', #{person.name}, #{person.age}, #{person.city})
        </foreach>
        END
        WHERE id IN
       <foreach collection="list" item="person" open="(" separator="," close=")">
            #{person.id}
        </foreach>
    </update>
</mapper>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有知识的山巅

文章对你有用,学到了知识。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值