接上篇
上次说实现隐私字段数据库存储加密想到两种方式,
- 一个是使用数据库的触发器,但是这种在查询的时候没有触发器,所以想在查询的时候反向解密,又要大量改代码,就麻烦了,加上隐私字段需要脱敏处理返回给前端所以采用第二种方法。
- 使用mybatis拦截器实现业务层和持久化层的数据处理、加密、解密、脱敏。(就像pagehelper分页插件实现路数一样),刚好有个公众号推了一篇文章苞米豆开发了商业项目mybatis-mate-starter,问了下需要收费(2021-11-18)个人版 99 ,企业版 499 ,虽然不贵但是我这边项目只需要加解密和脱敏处理正好练一下手就自己写了。
实现逻辑:
- 定义个注解作用域为类的属性上,用于标识这个属性需要加密或解密。
- 实现mybatis拦截器添加加解密逻辑。
- 加解密逻辑:判断如果是新增和更新操作拿到该注解属性的原值进行加密,如果是查询操作就拿到数据库值反向解密。
实现代码:
https://gitee.com/china-zhz/privacy-spring-boot-starter.git
这是spring-boot-starter项目,我已经创建了发行版,也可以直接引用该依赖使用:
<dependency>
<groupId>com.gitee.china-zhz</groupId>
<artifactId>privacy-spring-boot-starter</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
依赖下载失败可以添加依赖仓库到项目中:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
使用方式:
- 引入依赖后把注解放到要加的类属性上如:
@Data
@TableName("user")
@ApiModel(value = "UserPo对象", description = "本系统用户表")
public class UserPo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
@JsonFormat(shape = JsonFormat.Shape.STRING)
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@ApiModelProperty(value = "用户姓名")
private String userName;
@ApiModelProperty(value = "密码")
@FieldEncrypt
private String password;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "邮箱")
private String email;
@ApiModelProperty(value = "创建时间")
private LocalDateTime createDate;
@ApiModelProperty(value = "更新时间")
private LocalDateTime updateDate;
}
- 然后调用接口就可以了
效果:
插入更新效果图
查询效果图:
备注:
① @FieldEncrypt 注解默认使用AES算法,现在是集成了两种算法MD5和AES ,MD5是不可逆算法不可以解密,AES可以反向解密,默认的AES加密解密时我固定了一个秘钥,如果想自定义秘钥有两种方式:
- 全局配置yml文件里
privacy:
crypto:
key: jshfdiwhfkjncwolmas
- .加注解上
@ApiModelProperty(value = "密码")
@FieldEncrypt(key = "qwertyuiop")
private String password;
注解秘钥优先级高于全局秘钥
② 如果你想使用MD5加密
@ApiModelProperty(value = "密码")
@FieldEncrypt(algorithm = Algorithm.MD5)
private String password;
③ 如果这两个都不想用可以自定义加密解密器只需要实现ICrypto接口自定义加密解密方法,在注解属性里指定该类即可
@Slf4j
public class MyCrypto implements ICrypto {
@Override
public String encrypt(Algorithm algorithm, String s, String s1) throws Exception {
log.debug("---------------------------"+s+s1);
return "zxcvbnm";
}
@Override
public String decrypt(Algorithm algorithm, String s, String s1) throws Exception {
log.debug("---------------------------"+s+s1);
return "mnbvcxz";
}
}
脱敏处理功能已添加,注解为@FieldDesensitize,使用方式和加密一样简单自动识别手机号码、邮箱、银行卡号、身份证号码,可以自定义填充值,默认是星号,可以自定义脱敏器。
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("user")
@ApiModel(value="UserPo对象", description="本系统用户表")
public class UserPo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
@JsonFormat(shape = JsonFormat.Shape.STRING)
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@ApiModelProperty(value = "用户姓名")
private String userName;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "手机号")
private String phone;
@FieldDesensitize(fillValue = "#")
@ApiModelProperty(value = "邮箱")
private String email;
@ApiModelProperty(value = "创建时间")
private LocalDateTime createDate;
@ApiModelProperty(value = "更新时间")
private LocalDateTime updateDate;
}
项目问题欢迎讨论指正,也可以贡献自己的代码到仓库。