java使用注解实现字段脱敏
最近进行接口迁移的时候,有些敏感信息需要脱敏透出,但一个一个的调用脱敏工具类比较冗余,为了降低代码耦合,就想着用注解实现下
正文
1. 定义一个注解
1 2 3 4 5 6 7 8 | @Retention (RetentionPolicy.RUNTIME) @Target (ElementType.FIELD) @JacksonAnnotationsInside @JsonSerialize (using = SensitiveJsonSerializer. class ) public @interface Sensitive { //脱敏策略 SensitiveStrategy strategy(); } |
2. 定制一个脱敏策略
根据业务需求,实现脱敏规则(详细脱敏规则就不放出来了,各位可以自行百度,或者在hutool上找)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public enum SensitiveStrategy { USERNAME(SenstiveFieldUtil::senstiveName), IDCLARD(SenstiveFieldUtil::senstiveIdCard), PHONE(SenstiveFieldUtil::senstivePhone), ADDRESS(SenstiveFieldUtil::senstiveAddress); private final Function<String, String> desensitizer; SensitiveStrategy(Function<String, String> desensitizer){ this .desensitizer = desensitizer; } public Function<String, String> densitizer(){ return desensitizer;} } |
3. 定制json序列化实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer { private SensitiveStrategy strategy; @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeString(strategy.desensitizer().apply(value)); } /** * 获取属性上的注解属性 */ @Override public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { Sensitive annotation = property.getAnnotation(Sensitive. class ); if (Objects.nonNull(annotation)&&Objects.equals(String. class , property.getType().getRawClass())) { this .strategy = annotation.strategy(); return this ; } return prov.findValueSerializer(property.getType(), property); } } |
4. 定制json序列化实现
在透出的实体类中进行字段脱敏,使用@Sensitive注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | @Data public class UserInfo { /** * 真实姓名 */ @Sensitive (strategy = SensitiveStrategy.USERNAME) private String realName; /** * 地址 */ @Sensitive (strategy = SensitiveStrategy.ADDRESS) private String address; /** * 电话号码 */ @Sensitive (strategy = SensitiveStrategy.PHONE) private String phoneNumber; /** * 身份证号码 */ @Sensitive (strategy = SensitiveStrategy.IDCARD) private String idCard; } |
5. 测试
1 2 3 4 5 6 7 8 9 10 11 12 | @RestController public class TestController { @GetMapping ( "/test" ) public Person test(){ Person user = new Person(); user.setRealName( "王瑞" ); user.setPhoneNumber( "19796328206" ); user.setAddress( "四川省成都市武侯区倪家桥路地铁站3栋1204" ); user.setIdCard( "4333333333334334333" ); return user; } } |
结果:
1 2 3 4 5 6 | { "realName" : "*瑞" , "address" : "四川省成都市************3栋1204" , "phoneNumber" : "197****8206" , "idCard" : "4333****34333" } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律