Mybatis使用TypeHandler實現數據的加解密轉換


參考:
 
前段時間收到這么個需求:為安全起見,要求在數據庫里保存的所有敏感信息(電話號碼、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> {
……
}
這樣,在就可以省去第二步的大面積引用了。
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM