Mybatis使用TypeHandler实现数据的加解密转换

参考:

MyBatis之TypeHandler: https://www.cnblogs.com/yulinfeng/p/5991170.html

前段时间收到这么个需求:为安全起见,要求在数据库里保存的所有敏感信息(电话号码、email、身份证号码等等)都得加密。要是全都在java代码里控制,那就太麻烦了。还好mbatis有TypeHandler可以很好的解决这个问题。一劳永逸。

(如上面链接,这种方法可以被用来做任何类型转换的功能。)

第一步,先自定义一个类,继承自BaseTypeHandler:

public class AESEncryptHandler extends BaseTypeHandler {

@Override

public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {

ps.setString(i, AES.encrypt((String)parameter));

}

@Override

public String getNullableResult(ResultSet rs, String columnName) throws SQLException {

String columnValue = rs.getString(columnName);

return AES.decrypt(columnValue);

}

@Override

public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

String columnValue = rs.getString(columnIndex);

return AES.decrypt(columnValue);

}

@Override

public String getNullableResult(CallableStatement cs, int columnIndex)

throws SQLException {

String columnValue = cs.getString(columnIndex);

return AES.decrypt(columnValue);

}

}

 

其中,AES.encrypt()和AES.decrypt()分别是用AES算法实现的加解密函数。实现内容如下:

 

public class AES {

private static final String DEFAULT_PUBLIC_KEY = "asdfghjkloiuytre"; //内容随便,16位

 

public static String encrypt(String src) {

byte[] data = src.getBytes();

byte[] key = DEFAULT_PUBLIC_KEY.getBytes();

try {

SecretKeySpec secretKey = new SecretKeySpec(key, "AES");

byte[] enCodeFormat = secretKey.getEncoded();

SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");

Cipher cipher = Cipher.getInstance(ConfigureEncryptAndDecrypt.AES_ALGORITHM);// 创建密码器

cipher.init(Cipher.ENCRYPT_MODE, seckey);// 初始化

byte[] result = cipher.doFinal(data);

return new String(result);

} catch (Exception e) {

throw new RuntimeException("encrypt fail!", e);

}

}

 

public static String decrypt(String src) {

byte[] data = src.getBytes();

byte[] key = DEFAULT_PUBLIC_KEY.getBytes();

try {

SecretKeySpec secretKey = new SecretKeySpec(key, "AES");

byte[] enCodeFormat = secretKey.getEncoded();

SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");

Cipher cipher = Cipher.getInstance(ConfigureEncryptAndDecrypt.AES_ALGORITHM);// 创建密码器

cipher.init(Cipher.DECRYPT_MODE, seckey);// 初始化

byte[] result = cipher.doFinal(data);

return new String(result);

} catch (Exception e) {

throw new RuntimeException("decrypt fail!", e);

}

}

}

 

第二步,在mapper.xml里的对应字段上加上引用:

1)在resultMap上加引用,对应从数据库里取数据时转换成JAVA对象时的解密。

<resultMap type="DemoEntity" id="demoMap">

……

<result property="mobile" column="MOBILE" jdbcType="VARCHAR" typeHandler="com.demo.mybatis.handler.AESEncryptHandler"/>

……

</resultMap>

 

2)在sql语句中加入引用,对应从JAVA对像想数据库传递数据的加密动作(所有用到敏感信息的地方都要加):

<insert id="add" useGeneratedKeys="true" keyProperty="id" keyColumn="id" parameterType="demoMap" flushCache="true">

insert into tbl_donate_order

(

……

mobile,

……

)

values

(

……

#{mobile,jdbcType=VARCHAR,typeHandler=com.demo.mybatis.handler.AESEncryptHandler},

……

)

</insert>

第三步,在mybatis-config.xml中注册

<typeHandlers>

<package name="com.demo.mybatis.handler"></package>

</typeHandlers>

网上大多是注册到具体的类,我注册了包名,这样在这个包下的所有自定义类都可以被typeHandler使用了。

另外,

有的时候,如果我们需要对某个类型的所有数据进行转换的时候,可以这样定义类:

如,对DECIMAL和自定义的DemoDecimal转换:

@MappedJdbcTypes(JdbcType.DECIMAL)

@MappedTypes(DemoDecimal.class)

public class AmountTypeHandler extends BaseTypeHandler<DemoDecimal> {

……

}

这样,在就可以省去第二步的大面积引用了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值