背景:公司需要将部分验证码进行加密入库,查询的时候解密。
初始时:在每次的逻辑代码中,涉及到该字段的新增,修改,都需要对指定字段进行加密。查询的时候对字段进行解密(缺点:可维护性太差)
改进后:使用mybatis的TypeHandler进行配置后,自动进行对指定字段进行加解密。
下面看下配置吧!
一、首先自定义一个TypeHandler,我这里继承的BaseTypeHandler。
继承后重写4个父类方法即可。根据自己的业务要求可以改变逻辑(我们公司是加解密,其他对字段的操作都可以写这里)
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(value = String.class)
public class SafetyAESTypeHandler extends BaseTypeHandler {
/**
* 插入数据库时加密
*
* @param ps
* @param i
* @param parameter
* @param jdbcType
* @throws SQLException
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, SafetyAESConstant.PREFIX + AESUtils.AESEncode(SafetyAESConstant.aesPassword, (String) parameter));
}
/**
* 查询时解密
*
* @param rs
* @param columnName
* @return
* @throws SQLException
*/
@Override
public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
String result = rs.getString(columnName);
if (StringUtils.isNotBlank(result)) {
if (result.startsWith(SafetyAESConstant.PREFIX)) {
return AESUtils.AESDncode(SafetyAESConstant.aesPassword, result.substring(SafetyAESConstant.PREFIX_LEN));
}
}
return result;
}
/**
* 查询时解密
*
* @param rs
* @param columnIndex
* @return
* @throws SQLException
*/
@Override
public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String result = rs.getString(columnIndex);
if (StringUtils.isNotBlank(result)) {
if (result.startsWith(SafetyAESConstant.PREFIX)) {
return AESUtils.AESDncode(SafetyAESConstant.aesPassword, result.substring(SafetyAESConstant.PREFIX_LEN));
}
}
return result;
}
/**
* 查询时解密
*
* @param cs
* @param columnIndex
* @return
* @throws SQLException
*/
@Override
public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String result = cs.getString(columnIndex);
if (StringUtils.isNotBlank(result)) {
if (result.startsWith(SafetyAESConstant.PREFIX)) {
return AESUtils.AESDncode(SafetyAESConstant.aesPassword, result.substring(SafetyAESConstant.PREFIX_LEN));
}
}
return result;
}
}
二、在myabtis自动生成mapper等文件时,配置generatorConfig.xml
对需要处理的字段加上配置
<columnOverride column="old_value" jdbcType="VARCHAR" typeHandler="com.qkwl.service.user.handler.SafetyAESTypeHandler"/>
typeHandler属性,指定该列使用到的TypeHandler,配置类型处理器的全限定名
<table schema="" tableName="f_user" domainObjectName="UserEntity"
modelType="flat" mapperName="base.UserBaseMapper"
enableSelectByPrimaryKey="true" enableSelectByExample="true"
enableDeleteByPrimaryKey="true" enableDeleteByExample="true"
enableUpdateByPrimaryKey="true" enableUpdateByExample="true"
enableCountByExample="true" enableInsert="true">
<generatedKey column="fid" sqlStatement="MySql" identity="true"/>
<columnOverride column="fauthenticator" jdbcType="VARCHAR" typeHandler="com.service.user.handler.SafetyAESTypeHandler"/>
<columnOverride column="furl" jdbcType="VARCHAR" typeHandler="com.service.user.handler.SafetyAESTypeHandler"/>
</table>
三、自动生成后,mapper.xml
resultMap中返回的字段中,会带上typeHandler="com.service.user.handler.SafetyAESTypeHandler"
<result column="fauthenticator" jdbcType="VARCHAR" property="fauthenticator" typeHandler="com.service.user.handler.SafetyAESTypeHandler" />
<result column="furl" jdbcType="VARCHAR" property="furl" typeHandler="com.service.user.handler.SafetyAESTypeHandler" />
1.第一个注意点
因为有时候我们不是一开始就使用这个操作字段。
所以很多的select返回都是对应的实体类,这样的话,这个字段实际是没有在查询的时候进行解密。
使用到需要自定义字段的resultType改为resultMap。
2.第二个注意点
我们后面自己手动加的insert和update一定也要注意,加上typeHandler属性,不然的话不会加密保存,如果需要根据这个字段delete的话,也需要!!
#{fauthenticator,jdbcType=VARCHAR,typeHandler=com.service.user.handler.SafetyAESTypeHandler}
总结:感觉开发的时候使用还是很简单。但是对于刚接手这个模块的人需要去提醒他这些配置问题,不然后来的人也不知道为什么就没有加密啦。
如果有问题,请各位指出,非常感谢!!