当前位置: 首页 > news >正文

自定义注解结合策略模式实现数据脱敏

自定义注解结合策略模式实现数据脱敏

    • 数据脱敏
    • 常见的脱敏方式
    • 前端脱敏实现
    • 代码实现
      • pom 文件
      • 启动类
      • 配置文件
      • controller、service、dao
      • 最终效果

数据脱敏

在这里插入图片描述

常见的脱敏方式

在这里插入图片描述
基于成本的衡量,目前数据库层脱敏的不多,更多是前端脱敏,所以下面演示一种前端脱敏方案

前端脱敏实现

实现:后端把原始数据entity拿到后,放入vo类里面,而在 vo 类里给JavaBean字段标注注解 @Desensitive,后端返回前端之前,自动把这部分数据进行脱敏计算
在这里插入图片描述

代码实现

项目就是Springboot3+Mybatis-plus

pom 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.4</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example.springbootV3</groupId><artifactId>springbootV3</artifactId><version>0.0.1-SNAPSHOT</version><name>springbootV3</name><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>3.4.4</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

启动类

@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class DemoApplication{public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

配置文件

spring.datasource.url=jdbc:mysql://192.168.133.128:3306/wxpay?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Drivermybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.mapper-locations=classpath*:mapper/*.xml

controller、service、dao

@RestController
@RequestMapping("/api/user")
public class UserController {@Autowiredprivate UserService userService;@Autowiredprivate DesensitiveComponent desensitiveComponent;@GetMapping("selectById/{id}")public ResultData<UserVo> selectById(@PathVariable("id") Integer id){try {User user = userService.getById(id);UserVo userVo = new UserVo();desensitiveComponent.desensitive(user, userVo);return ResultData.success(userVo);} catch (IllegalAccessException e) {return ResultData.fail(ReturnCodeEnum.HANDLE_FAILED.getCode(), "处理失败");}}
}
@Component
public class DesensitiveComponent {@Autowiredprivate List<DesensiveStrategy> desensiveStrategies;public void desensitive(Object source, Object vo) throws IllegalAccessException {// 将eneity属性拷贝到 vo 中BeanUtils.copyProperties(source, vo);// 给vo进行脱敏Field[] fields = vo.getClass().getDeclaredFields();// 遍历所有字段,判断是否有 @Desesitive注解for (Field field : fields) {if (field.isAnnotationPresent(Desensive.class)) {field.setAccessible(true);Object fieldValue = field.get(vo);//拿到注解的typeDesensive annotation = field.getAnnotation(Desensive.class);DesensiveType type = annotation.type();// 根据不同的类型调用不同的脱敏策略for (DesensiveStrategy stratege : desensiveStrategies) {if (stratege.support(type)) {String result = stratege.desensiveStrategy((String) fieldValue);field.set(vo, result);}}}}}
}
/*** 脱敏的字段类型*/
public enum DesensiveType {DEFAULT,CARD,PHONE,EMAIL
}
public interface UserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Desensive {DesensiveType type() default DesensiveType.DEFAULT;
}
@TableName("t_user")
@Data
public class User {@TableIdprivate Integer id;private String name;private Integer age;private String phone;private String card;private Date createTime;
}
@Data
public class UserVo {private Integer id;private String name;private Integer age;@Desensive(type = DesensiveType.PHONE)private String phone;@Desensive(type = DesensiveType.CARD)private String card;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private Date createTime;
}
public interface DesensiveStrategy {boolean support(DesensiveType type);String desensiveStrategy(String target);
}
@Component
public class PhoneDesensiveStrategy implements DesensiveStrategy{@Overridepublic boolean support(DesensiveType type) {return type.equals(DesensiveType.PHONE);}@Overridepublic String desensiveStrategy(String phone) {if (phone.length() == 11){return  phone.substring(0, 3) + "****" + phone.substring(7, 11);}return "***********";}
}
@Component
public class CardDesensiveStrategy implements DesensiveStrategy{@Overridepublic boolean support(DesensiveType type) {return type.equals(DesensiveType.CARD);}@Overridepublic String desensiveStrategy(String card) {if (card.length() > 10) {return card.substring(0, 6).concat("******");}return "~~~~~~~~";}
}

最终效果

在这里插入图片描述

http://www.dtcms.com/a/544395.html

相关文章:

  • 【金仓数据库产品体验官】Apache James适配金仓数据库
  • VR公共安全学习机-VR校园健康饮食科普系统-VR食品安全体验系统
  • 【微服务】SpringBoot 整合Neo4j 图数据库项目实战详解
  • 模板网站系统wordpress首页描述
  • 图书网站策划书网站的维护方案
  • 【Android】Android Framework 的那些核心子系统及其功能详解
  • Android车载多媒体开发MediaSession框架理解
  • 掌握Axios:前端HTTP请求全攻略
  • 产业链、技术与政策:智能网联新能源汽车的“十五五”蓝图
  • 20251029让AIO-3576Q38开发板适配Rockchip的原厂Android14之后配置为禁止锁屏
  • 解析视频融合平台EasyCVR如何以跨平台与兼容性技术重构安防融合中台
  • SQlite:外键约束
  • linux命令-网络工具-3
  • Android 通信机制简析
  • C++ 虚函数的使用开销以及替代方案
  • 椒江网站建设百度手机助手app安卓版官方下载
  • 柯桥做网站的公司怎么查网站是用什么语言做的
  • Unity功能篇:UI和模型高亮
  • Rust | 不只是 async:Actix-web 请求生命周期与 Actor 模型的并发艺术
  • 如何选择专业网站开发商丰台建站推广
  • Kotlin List扩展函数使用指南
  • 重组蛋白与传统蛋白的区别:从来源到特性的全面解析
  • Ubuntu24.04 最小化发布 需要删除的内容
  • 深入理解 Rust 的 LinkedList:双向链表的实践与思考
  • 将一个List分页返回的操作方式
  • 使用Storage Transfer Service 事件驱动型 — 将AWS S3迁移到 GCP Cloud Storage
  • 苏州外贸网站建设赣州网上银行登录
  • Blender动画笔记
  • python学习之正则表达式
  • SCRM平台对比推荐:以企业微信私域运营需求为核心的参考