在使用MyBatis框架处理数据库中的MEDIUMBLOB字段(例如存储图片或视频等二进制大对象)时,数据安全问题始终是开发人员不可回避的挑战。MyBatis本身并未提供内置的加密与解密功能,这意味着若希望对存入MEDIUMBLOB的数据实施加密保护,必须在Java应用层自行实现加密逻辑。

具体应如何操作?一种常见且行之有效的方案是采用AES对称加密算法。接下来,我们将通过一个完整的代码示例,逐步演示从引入加密依赖到在MyBatis中集成使用的全流程。
第一步:引入加密库依赖
首先,请确保项目中已引入支持AES加密的第三方库。如果你使用Maven管理项目,可在pom.xml中添加Bouncy Castle这一强大的加密提供者,它提供了所需的算法实现。
org.bouncycastle
bcprov-jdk15on
1.68
org.bouncycastle
bcpkix-jdk15on
1.68
第二步:编写AES加密工具类
依赖就绪后,接下来需要实现核心的加密与解密逻辑。创建一个名为AESUtil的工具类,将加密、解密方法封装起来,便于后续调用。
先看加密方法。本例采用AES/CBC/PKCS5Padding模式,该模式需要初始化向量(IV)以增强安全性。为演示清晰,我们使用一个固定的IV,但在生产环境中,IV的生成与管理必须更加严谨。
import ja vax.crypto.Cipher;
import ja vax.crypto.spec.IvParameterSpec;
import ja vax.crypto.spec.SecretKeySpec;
import ja va.nio.charset.StandardCharsets;
import ja va.util.Base64;
public class AESUtil {
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
public static String encrypt(String data, String key) throws Exception {
IvParameterSpec iv = new IvParameterSpec("1234567812345678".getBytes(StandardCharsets.UTF_8));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
}
}
接着是对应的解密方法。解密是加密的逆过程,使用相同的密钥与IV,将Base64编码的密文还原为原始数据。
public static String decrypt(String encryptedData, String key) throws Exception {
IvParameterSpec iv = new IvParameterSpec("1234567812345678".getBytes(StandardCharsets.UTF_8));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
return new String(original);
}
第三步:在MyBatis中集成使用
工具类已准备妥当,现在需要将它融入MyBatis的数据库操作流程中。核心思路是:仍然使用MyBatis的标准方式来映射和操作MEDIUMBLOB字段,只是在数据写入数据库之前和从数据库读出之后,分别调用加密与解密方法即可。
首先,在Mapper XML文件中,像往常一样定义resultMap与SQL语句。注意,blob_data字段映射为java.sql.Blob类型。
UPDATE your_table SET blob_data = #{blobData, jdbcType=BLOB} WHERE id = #{id}
然后,在Java业务逻辑层中,整个流程变得清晰明了:
- 查询数据:首先通过MyBatis查询原始Blob数据。
- 加密处理:将Blob数据转为字节数组,并调用
AESUtil.encrypt进行加密。 - 更新数据:将加密后的字符串(根据字段定义,可能需要再转为Blob或字节数组)通过MyBatis写回数据库。
- 验证解密:再次查询加密后的数据,调用
AESUtil.decrypt进行解密,以验证流程的正确性。
// 查询数据
YourModel model = sqlSession.selectOne("com.example.YourMapper.selectYourData", id);
// 加密blobData
String encryptedData = AESUtil.encrypt(model.getBlobData().getBytes(), "yourEncryptionKey");
// 更新数据
sqlSession.update("com.example.YourMapper.updateYourData", new YourModel(encryptedData, model.getId()));
// 查询数据以验证
YourModel updatedModel = sqlSession.selectOne("com.example.YourMapper.selectYourData", id);
String decryptedData = AESUtil.decrypt(updatedModel.getBlobData(), "yourEncryptionKey");
至此,一个基础的MyBatis集成AES加密解密流程已经完成。不过需要特别提醒:上述示例为演示简洁,在密钥(yourEncryptionKey)和初始化向量(IV)的处理上做了简化。在实际生产环境中,密钥的安全存储、动态IV的生成与使用,都是必须严肃对待的安全要点,绝不能像示例中那样将敏感信息硬编码在代码里。
