mybatis-data-security实现数据库数据加解密
Posted justry_deng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis-data-security实现数据库数据加解密相关的知识,希望对你有一定的参考价值。
mybatis-data-security
介绍
mybatis-data-security提供了一种基于注解实现数据库数据加解密的功能支持。
原理
编写mybatis interceptor实现,对业务代码无侵入,在入库前加密,出库前解密。
前置条件
- 项目采用mybatis作为持久层框架
功能特性
- 项目启动时分析并校验加解密信息,若使用不当则快速失败
- 支持直接对String类型的变量进行加解密(示例见下述步骤4)
- 支持对POJO中String类型的字段进行加解密(示例见下述步骤4)
- 支持自定义加解密实现
注意事项
目前而言,加密后的密文/解密后的明文都会回写给原来的对象;但是有的时候,我们不希望加解密直接操作原来的对象,而是希望加解密时操作原对象的clone对象时,
就可以通过实现com.ideaaedi.mybatis.data.security.support.PojoCloneable
接口来达到这个目的。
一般的,在下述场景下比较需要这种能力:
- 入库加密时,加密后的密文不要回写到原来的对象中 —— 因为在某些业务场景下,入库后,后面的程序逻辑还需要取对应的明文值而不是密文值。
- 出库解密时,解密后的明文不要回写到原来的对象中 —— 因为在某些业务场景下,出库后,后面的一些程序逻辑需要修改查询出来的对象的属性值, 你这里修改后;当别人使用相同的sql查询时,因为某些缓存机制的存在,就可能导致别人查出来的对象就是你现在在操作着的对象,随意这个对象 的值比起数据库数据来说,是"失真"了的
使用说明
- 引入相关依赖
<dependency> <groupId>com.idea-aedi</groupId> <artifactId>mybatis-data-security</artifactId> <version>${version}</version> </dependency>
- 使用注解
com.ideaaedi.mybatis.data.security.annotation.EnableMybatisDataSecurity
,启用mybatis-data-security功能@SpringBootApplication @EnableMybatisDataSecurity public class YourApplication { // ... }
- 实现
com.ideaaedi.mybatis.data.security.support.EncryptExecutor
,定制加解密逻辑import com.ideaaedi.mybatis.data.security.annotation.Encrypt; import com.ideaaedi.mybatis.data.security.support.EncryptExecutor; import com.ideaaedi.mybatis.data.security.util.AesUtil; import org.springframework.stereotype.Component; /** * 实现自己的加解密器 - 示例 * * @author JustryDeng * @since 2021/2/11 19:08:05 */ @Component public class MyEncryptExecutor implements EncryptExecutor { @Override public String encryptParameter(String paramName, String paramValue, Encrypt annotation) { return AesUtil.encrypt(paramValue); } @Override public String encryptField(String fieldName, String fieldValue, Encrypt annotation, Object pojo) { return AesUtil.encrypt(fieldValue); } @Override public String decryptField(String fieldName, String fieldValue, Encrypt annotation, Object pojo) { return AesUtil.decrypt(fieldValue); } }
- 使用注解
com.ideaaedi.mybatis.data.security.annotation.Encrypt
控制要加解密的字段
- 示例一:直接对String类型的变量加密
- case 1:
@Insert("INSERT INTO employee (`id`,`name`) VALUES(#{id}, #{name})"); int insertThree(@Param("id")int id, @Param("name") @Encrypt String name);
- case 2:
@MapKey("id") @Select("SELECT `id`,`name`,`age`,`gender`,`motto`,`birthday`,`hobby` FROM `employee` WHERE name = #{name}"); Map<Integer, Employee> selectMapByName(@Encrypt @Param("name") String name);
- case 1:
- 示例二:对POJO中String类型的字段加解密
- pojo示例:
@Data @Builder @NoArgsConstructor @AllArgsConstructor public class Employee { /** 用户id */ private Integer id; /** 名字 */ @Encrypt private String name; /** 年龄 */ private Integer age; /** 性别 */ private String gender; /** 座右铭 */ @Encrypt private String motto; /** 生日 */ private String birthday; /** 爱好 */ @Encrypt private String hobby; }
- case 1: 单POJO入参
@Insert("INSERT INTO employee (`id`,`name`, `age`, `gender`, `motto`, `birthday`, `hobby`) VALUES(#{u.id},#{u.name},#{u.age},#{u.gender},#{u.motto},#{u.birthday},#{u.hobby})") @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "u.id") int insertOne(@Param("u") Employee employee);
- case 2: 单POJO入参
@Insert("INSERT INTO employee (`id`, `name`, `age`, `gender`, `motto`, `birthday`, `hobby`) VALUES(#{id},#{name},#{age},#{gender},#{motto},#{birthday},#{hobby})") @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id") int insertTwo(Employee employee);
- case 3: POJO放在MAP中入参
@Insert("INSERT INTO employee (`id`, `name`, `age`) VALUES(#{u.id},#{u.name},#{u.age})") int insertEight(Map<String, Employee> paramsMap);
- case 4: POJO放在MAP中入参
@Insert("INSERT INTO employee (`id`,`name`, `age`) VALUES(#{p.u.id},#{p.u.name},#{p.u.age})") int insertNine(@Param("p") Map<String, Employee> paramsMap);
- case 5: POJO放在COLLECTION中入参
@InsertProvider(type = AbcMapperProvider.class, method = "insertTenProvider") int insertTen(List<Employee> employeeList);
- case 6: POJO放在COLLECTION中入参
@InsertProvider(type = AbcMapperProvider.class, method = "insertElevenProvider") int insertEleven(@Param("list") List<Employee> employeeList);
- case 7: POJO放在ARRAY中入参
@InsertProvider(type = AbcMapperProvider.class, method = "insertTwelveProvider") Integer insertTwelve(@Param("myArray") Employee[] employeeArray);
- case 8: 单POJO出参
@Select("SELECT `id`,`name`,`age`,`gender`,`motto`,`birthday`,`hobby` FROM `employee` WHERE id = #{id}") Employee selectOneById(@Param("id") Integer id);
- case 9: POJO放在COLLECTION中出参
@Select("SELECT `id`,`name`,`age`,`gender`,`motto`,`birthday`,`hobby` FROM `employee` ") List<Employee> selectAll();
- case 10: POJO放在ARRAY中出参
@Select("SELECT `id`,`name`,`age`,`gender`,`motto`,`birthday`,`hobby` FROM `employee` ") Employee[] selectAllAsArray();
- case 11: POJO放在MAP中出参
@Select("SELECT `id`,`name`,`age`,`gender`,`motto`,`birthday`,`hobby` FROM `employee` WHERE name = #{name}") Map<Integer, Employee> selectMapByName(@Encrypt @Param("name") String name);
- case 12: …
// ...
- pojo示例:
以上是关于mybatis-data-security实现数据库数据加解密的主要内容,如果未能解决你的问题,请参考以下文章