MyBatis-Plus数据安全保护(字段脱敏)
- 项目创建
- POM依赖
<dependency><!--MyBatis-Plus 企业级模块--> <groupId>com.baomidou</groupId> <artifactId>mybatis-mate-starter</artifactId> <version>1.2.8</version> </dependency>
- YML配置
spring: datasource: # 配置安全:https://blog.csdn.net/tongxin_tongmeng/article/details/128664932 url: mpw:IlcV2VrLIr+z3ruf0oHP1sV3JuEvntw9QZDEYhQWDNHJ9Xkm7qZokxkEeTCPNqma username: mpw:aoVz0lDJNymnmrhw6LkQow== password: mpw:StRVtLG7vB6iKVt83du7fw== driver-class-name: com.mysql.cj.jdbc.Driver # Mybatis Mate 配置 mybatis-mate: cert: # 请添加微信wx153666购买授权,不白嫖从我做起! 测试证书会失效,请勿正式环境使用 grant: thisIsTestLicense license: TtY9GC88CzSkEmUhzIyvM2MJKvsgPyxoNCExH4/GhaBwuTQ93aeLaR6/dM49wMSk+oQdmqUibCM8b5H74s1Nx+2C5V3U1gKiLtddVc8Eg8oC1F2nLxOiDKDvPpdxWFGsPW6mQE2LDr+tK8GXpFS3N8xwmYy/gHCwQ4Avqp9JqBbke7pZzL2adIlxYHmCYpfNTN+NRHIEFaGFTBlzZHDb3UfJaeqLaAtWBol0QOPEM69Kz3JSemxBHnEO1ID75bwwmkgqC7Ps4z9iYAK9GLzzaPwSiFELNCmIvwa5YSJLxP9NMQUWbVGIRqehxnVqfgx/68+yIfpByqGTMxLR33yeEQ==
- SQL脚本
CREATE TABLE `sentive` ( `id` BIGINT NOT NULL COMMENT '主键ID', `chineseName` VARCHAR ( 255 ) DEFAULT NULL COMMENT 'chineseName', `idCard` VARCHAR ( 255 ) DEFAULT NULL COMMENT 'idCard', `phone` VARCHAR ( 255 ) DEFAULT NULL COMMENT 'phone', `mobile` VARCHAR ( 255 ) DEFAULT NULL COMMENT 'mobile', `address` VARCHAR ( 255 ) DEFAULT NULL COMMENT 'address', `email` VARCHAR ( 255 ) DEFAULT NULL COMMENT 'email', `bankCard` VARCHAR ( 255 ) DEFAULT NULL COMMENT 'bankCard', `password` VARCHAR ( 255 ) DEFAULT NULL COMMENT 'password', `carNumber` VARCHAR ( 255 ) DEFAULT NULL COMMENT 'carNumber', PRIMARY KEY ( `id` ) ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;
- 代码生成(MybatisX)
@RestController @RequestMapping("/sensitive") public class SensitiveController { @Autowired private SensitiveService sensitiveService; @PostMapping("/create") public Boolean create(@RequestBody Sensitive sensitive) { return sensitiveService.save(sensitive); } @GetMapping("/get") public Sensitive get(@RequestBody Sensitive sensitive) { return sensitiveService.getById(sensitive.getId()); } @GetMapping("/getAll") public List<Sensitive> getAll() { return sensitiveService.list(); } @PutMapping("/update") public Boolean update(@RequestBody Sensitive sensitive) { return sensitiveService.updateById(sensitive); } @DeleteMapping("/delete") public Boolean delete(@RequestBody Sensitive sensitive) { return sensitiveService.removeById(sensitive); } @DeleteMapping("/deleteAll") public Boolean deleteAll() { return sensitiveService.remove(new QueryWrapper<>()); } }
- 脱敏策略
@Configuration public class SensitiveStrategyConfig { /** * 注入脱敏策略 */ @Bean public ISensitiveStrategy sensitiveStrategy() { return new SensitiveStrategy(); } }
- 字段脱敏(@FieldSensitive)
/** * * @TableName sentive */ @TableName(value ="sentive") @Data public class Sentive implements Serializable { /** * 主键ID */ @TableId(value = "id") private Long id; /** * chineseName */ @FieldSensitive(SensitiveType.chineseName) @TableField(value = "chineseName") private String chinesename; /** * idCard */ @FieldSensitive(SensitiveType.idCard) @TableField(value = "idCard") private String idcard; /** * phone */ @FieldSensitive(SensitiveType.phone) @TableField(value = "phone") private String phone; /** * mobile */ @FieldSensitive(SensitiveType.mobile) @TableField(value = "mobile") private String mobile; /** * address */ @FieldSensitive(SensitiveType.address) @TableField(value = "address") private String address; /** * email */ @FieldSensitive(SensitiveType.email) @TableField(value = "email") private String email; /** * bankCard */ @FieldSensitive(SensitiveType.bankCard) @TableField(value = "bankCard") private String bankcard; /** * password */ @FieldSensitive(SensitiveType.password) @TableField(value = "password") private String password; /** * carNumber */ @FieldSensitive(SensitiveType.carNumber) @TableField(value = "carNumber") private String carnumber; @TableField(exist = false) private static final long serialVersionUID = 1L; @Override public boolean equals(Object that) { if (this == that) { return true; } if (that == null) { return false; } if (getClass() != that.getClass()) { return false; } Sentive other = (Sentive) that; return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) && (this.getChinesename() == null ? other.getChinesename() == null : this.getChinesename().equals(other.getChinesename())) && (this.getIdcard() == null ? other.getIdcard() == null : this.getIdcard().equals(other.getIdcard())) && (this.getPhone() == null ? other.getPhone() == null : this.getPhone().equals(other.getPhone())) && (this.getMobile() == null ? other.getMobile() == null : this.getMobile().equals(other.getMobile())) && (this.getAddress() == null ? other.getAddress() == null : this.getAddress().equals(other.getAddress())) && (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail())) && (this.getBankcard() == null ? other.getBankcard() == null : this.getBankcard().equals(other.getBankcard())) && (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword())) && (this.getCarnumber() == null ? other.getCarnumber() == null : this.getCarnumber().equals(other.getCarnumber())); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); result = prime * result + ((getChinesename() == null) ? 0 : getChinesename().hashCode()); result = prime * result + ((getIdcard() == null) ? 0 : getIdcard().hashCode()); result = prime * result + ((getPhone() == null) ? 0 : getPhone().hashCode()); result = prime * result + ((getMobile() == null) ? 0 : getMobile().hashCode()); result = prime * result + ((getAddress() == null) ? 0 : getAddress().hashCode()); result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode()); result = prime * result + ((getBankcard() == null) ? 0 : getBankcard().hashCode()); result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode()); result = prime * result + ((getCarnumber() == null) ? 0 : getCarnumber().hashCode()); return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getClass().getSimpleName()); sb.append(" ["); sb.append("Hash = ").append(hashCode()); sb.append(", id=").append(id); sb.append(", chinesename=").append(chinesename); sb.append(", idcard=").append(idcard); sb.append(", phone=").append(phone); sb.append(", mobile=").append(mobile); sb.append(", address=").append(address); sb.append(", email=").append(email); sb.append(", bankcard=").append(bankcard); sb.append(", password=").append(password); sb.append(", carnumber=").append(carnumber); sb.append(", serialVersionUID=").append(serialVersionUID); sb.append("]"); return sb.toString(); } }
- 脱敏测试
脱敏前: { "chinesename": "童心同萌", "idcard": "111111", "phone": "222222", "mobile": "333333", "address": "444444", "email": "555555@qq.com", "bankcard": "666666", "password": "777777", "carnumber": "888888" } 注意:调用控制器接口向数据库插入数据
脱敏后: { "id": 1614933945059004418, "chinesename": "童***", "idcard": "**1111", "phone": "**2222", "mobile": "333*33", "address": "444444", "email": "555***@qq.com", "bankcard": "666666**6666", "password": "******", "carnumber": "88***8" } 注意:数据库存储内容为原始数据,查询时脱敏后得到的数据不再是原始数据,实现数据保护
-
自定义策略
@Configuration public class SensitiveStrategyConfig { /** * 注入脱敏策略 */ @Bean public ISensitiveStrategy sensitiveStrategy() { return new SensitiveStrategy() .addStrategy("strategyA", t -> t.toUpperCase().replace("A", "#")) .addStrategy("strategyB", t -> t.toUpperCase().replace("B", "$")) .addStrategy("strategyC", t -> t.toUpperCase().replace("C", "&")); } } 注意:strategyA strategyB strategyC 为自定义脱敏策略,字段添加@FieldSensitive("strategyA")注解 即可使用strategyA脱敏策略,该策略将原始数据转为大写后将所有"A"替换为"#",strategyB strategyC同理
/** * chineseName */ @FieldSensitive("strategyA") @TableField(value = "chineseName") private String chinesename; /** * idCard */ @FieldSensitive("strategyB") @TableField(value = "idCard") private String idcard; /** * phone */ @FieldSensitive("strategyC") @TableField(value = "phone") private String phone;