mybatis-plus
mybatis-plus copied to clipboard
AESEncryptHandler继承BaseTypeHandler实现部分字段加密解密,单条数据查询时不会进入AESEncryptHandler
当前使用版本(必填,否则不予处理)
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
该问题是如何引起的?(确定最新版也有问题再提!!!)
用原始数据查询数据时,无法自动将查询条件中的数据进行加密处理 ,但是列表查询时能自动解密插入时能自动加密
原因:
LambdaQueryWrapper中的eq方法无法对加@TableField(value = "system_key",typeHandler = AESEncryptHandler.class)进行加密处理
列表查询时:
==> Preparing: SELECT COUNT(*) AS total FROM system_config t
==> Parameters:
<== Columns: total
<== Row: 1
<== Total: 1
==> Preparing: SELECT t.system_config_id,t.system_key,t.system_value,t.description,t.created_by,t.updated_by,t.created_at,t.updated_at FROM system_config t LIMIT ?
==> Parameters: 10(Long)
<== Columns: system_config_id, system_key, system_value, description, created_by, updated_by, created_at, updated_at
<== Row: 1784376751312343041, S6EWmAkjdRveYd46NUYQ4w==, string, <<BLOB>>, 1111111111111111111, 1111111111111111111, 2024-04-28 08:19:04, 2024-04-28 08:19:04
<== Total: 1
结果(能自动进行解密处理):
{
"code": "000000",
"msg": "OK",
"explain": null,
"data": {
"pageSize": 10,
"current": 1,
"maxPage": 1,
"total": 1,
"list": [
{
"systemConfigId": "1784376751312343041",
"systemKey": "string",
"systemValue": "string",
"description": "string"
}
]
}
}
插入时:
@Override
public SystemConfig insert0(SystemConfig systemConfig) {
SystemConfig systemConfig1 = selectOneBySystemKey(systemConfig.getSystemKey());
if (Objects.isNull(systemConfig1)) {
if (systemConfigMapper.insert(systemConfig) == 0) {
throw new BusinessException(CodeEnums.S00000);
}
return systemConfig;
}
return systemConfig1;
}
能自动进行加密处理
==> Preparing: INSERT INTO system_config ( system_config_id, system_key, system_value, description, created_by, updated_by, created_at, updated_at ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )
==> Parameters: 1784398913226190850(String), S6EWmAkjdRveYd46NUYQ4w==(String), string(String), string(String), 1111111111111111111(String), 1111111111111111111(String), 2024-04-28T09:47:08.100658900(LocalDateTime), 2024-04-28T09:47:08.100658900(LocalDateTime)
重现步骤(如果有就写完整)
Server
@Override
public SystemConfig selectOneBySystemKey(String systemKey) {
LambdaQueryWrapper<SystemConfig> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemConfig::getSystemKey,systemKey);
return systemConfigMapper.selectOne(wrapper);
}
AESEncryptHandler 代码:
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes({String.class})
public class AESEncryptHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
EncryptProperty encryptProperty = BeanUtil.getBean(EncryptProperty.class);
String content = StringUtils.isBlank(parameter) ? "" : parameter;
ps.setString(i,EncryptUtil.aesEncryptData(encryptProperty.getAesKey(),content));
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
EncryptProperty encryptProperty = BeanUtil.getBean(EncryptProperty.class);
return EncryptUtil.aesDecryptDataString(encryptProperty.getAesKey(),rs.getString(columnName));
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
EncryptProperty encryptProperty = BeanUtil.getBean(EncryptProperty.class);
String columnValue = rs.getString(columnIndex);
return EncryptUtil.aesEncryptData(encryptProperty.getAesKey(),columnValue);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
EncryptProperty encryptProperty = BeanUtil.getBean(EncryptProperty.class);
String columnValue = cs.getString(columnIndex);
return EncryptUtil.aesEncryptData(encryptProperty.getAesKey(),columnValue);
}
}
实体类中加密属性:
@TableField(value = "system_key",typeHandler = AESEncryptHandler.class)
private String systemKey;
Mapper.xml:
<result property="systemKey" column="system_key" jdbcType="VARCHAR" typeHandler="cloud.astrsea.preprocessing.handler.AESEncryptHandler"/>
请求参数
{
"systemKey": "string",
}
报错信息
数据未被加密
==> Preparing: SELECT system_config_id,system_key,system_value,description,created_by,updated_by,created_at,updated_at FROM system_config WHERE (system_key = ?)
==> Parameters: string(String)
<== Total: 0
复现了一下最新版3.5.6也存在这个问题
问题发生在AbstractWrapper.addCondition()和AbstractWrapper.formatParam()中,本应该拼接成 system_key=#{systemKey,typeHandler=cloud.astrsea.preprocessing.handler.AESEncryptHandler},却拼接成system_key=#{ew.paramNameValuePairs.MPGENVAL1}
问题发生在AbstractWrapper.addCondition()和AbstractWrapper.formatParam()中,本应该拼接成 system_key=#{systemKey,typeHandler=cloud.astrsea.preprocessing.handler.AESEncryptHandler},却拼接成system_key=#{ew.paramNameValuePairs.MPGENVAL1}
那这个应该怎么处理
问题发生在AbstractWrapper.addCondition()和AbstractWrapper.formatParam()中,本应该拼接成 system_key=#{systemKey,typeHandler=cloud.astrsea.preprocessing.handler.AESEncryptHandler},却拼接成system_key=#{ew.paramNameValuePairs.MPGENVAL1}
那这个应该怎么处理
我不知道这个是特性还是bug,@nieqiurong 如果是bug的话,希望能让我提交pr
使用姿势不对吧。看代码注释说typeHandler要配合 TableName.autoResultMap() 一起使用
使用姿势不对吧。看代码注释说typeHandler要配合 TableName.autoResultMap() 一起使用
我这边在mapper里面用了,所以autoResultMap = true可以不使用
<result property="systemKey" column="system_key" jdbcType="VARCHAR" typeHandler="cloud.astrsea.preprocessing.handler.AESEncryptHandler"/>
新版本查询有说支持query自动调用handler吗?看原来issue用法如下: https://github.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2UserTest.java testLambdaTypeHandler
QueryWrapper<Customer> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda() .apply("cert_no={0,typeHandler=" + EncryptHandler.class.getCanonicalName() + "}", "test1234"); Customer customer = customerService.getOne(queryWrapper);
我已找到select自动调用handler的方法
@miemieYaho 那能否让LambdaQueryWrapper中自动handler,使查询值自动加密,实现加密字段的查询
用wrapper.apply("cert_no={0,typeHandler="+ EncryptHandler.class.getCanonicalName()+ "}", "test1234");
用wrapper.apply("cert_no={0,typeHandler="+ EncryptHandler.class.getCanonicalName()+ "}", "test1234");
为什么要使用这种复杂又难写的方式呢,如果能自动适配不是更好?是考虑什么原因