几天前使用了Jackson对数据的自定义序列化。突发灵感,利用此方法来简单实现接口返回数据脱敏,故写此文记录。

核心思想是利用Jackson的StdSerializer,@JsonSerialize,以及自己实现的数据脱敏过程。

使用效果如下:

首先在需要进行脱敏的VO字段上面标注相关脱敏注解

调用接口即可看到脱敏效果

实现过程如下:

1. 定义脱敏的过程实现

/**
* Created by EalenXie on 2021/9/24 15:52
* 顶级的脱敏器
*/
public interface Desensitization<T> { /**
* 脱敏实现
*
* @param target 脱敏对象
* @return 脱敏返回结果
*/
T desensitize(T target); }

比如具体的手机号脱敏器实现


import com.github.Symbol; import java.util.regex.Matcher;
import java.util.regex.Pattern; /**
* Created by EalenXie on 2021/9/24 15:56
* 手机号脱敏器 默认只保留前3位和后4位
*/
public class PhoneDesensitization implements StringDesensitization { /**
* 手机号正则
*/
private static final Pattern DEFAULT_PATTERN = Pattern.compile("(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}"); /**
* 手机号脱敏 只保留前3位和后4位
*/
@Override
public String desensitize(String target) {
Matcher matcher = DEFAULT_PATTERN.matcher(target);
while (matcher.find()) {
String group = matcher.group();
target = target.replace(group, group.substring(0, 3) + Symbol.getSymbol(4, Symbol.STAR) + group.substring(7, 11));
}
return target;
}
}
2.定义脱敏注解,并指明了使用的序列化器,注解中声明了使用的脱敏器实现

package com.github.annotation; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.github.desensitization.Desensitization;
import com.github.serializer.ObjectDesensitizeSerializer; import java.lang.annotation.*; /**
* Created by EalenXie on 2021/10/8 11:30
*/
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = ObjectDesensitizeSerializer.class)
@Documented
public @interface Desensitize {
/**
* 脱敏器实现
*/
@SuppressWarnings("all")
Class<? extends Desensitization<?>> desensitization();
}
3. 实现定义的序列化器

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.github.Symbol;
import com.github.annotation.Desensitize;
import com.github.desensitization.Desensitization;
import com.github.desensitization.DesensitizationFactory;
import com.github.desensitization.StringDesensitization; import java.io.IOException; /**
* Created by EalenXie on 2021/8/9 9:03
* 脱敏序列化器
*/
public class ObjectDesensitizeSerializer extends StdSerializer<Object> implements ContextualSerializer { private transient Desensitization<Object> desensitization; protected ObjectDesensitizeSerializer() {
super(Object.class);
} public Desensitization<Object> getDesensitization() {
return desensitization;
} public void setDesensitization(Desensitization<Object> desensitization) {
this.desensitization = desensitization;
} @Override
public JsonSerializer<Object> createContextual(SerializerProvider prov, BeanProperty property) {
Desensitize annotation = property.getAnnotation(Desensitize.class);
return createContextual(annotation.desensitization());
} @SuppressWarnings("unchecked")
public JsonSerializer<Object> createContextual(Class<? extends Desensitization<?>> clazz) {
ObjectDesensitizeSerializer serializer = new ObjectDesensitizeSerializer();
if (clazz != StringDesensitization.class) {
serializer.setDesensitization((Desensitization<Object>) DesensitizationFactory.getDesensitization(clazz));
}
return serializer;
} @Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
Desensitization<Object> objectDesensitization = getDesensitization();
if (objectDesensitization != null) {
try {
gen.writeObject(objectDesensitization.desensitize(value));
} catch (Exception e) {
gen.writeObject(value);
}
} else if (value instanceof String) {
gen.writeString(Symbol.getSymbol(((String) value).length(), Symbol.STAR));
} else {
gen.writeObject(value);
}
}
}
4.代码的设计说明

完整代码可见 : https://github.com/EalenXie/jackson-desensitize

另附 基于Logback的日志脱敏方案(笔者认为这可能是全网最简单快捷的)

原理是利用Logback的自定义日志转换器ClassicConverter

1. 自定义脱敏日志转换器

import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.github.desensitization.EmailDesensitization;
import com.github.desensitization.IDCardDesensitization;
import com.github.desensitization.PhoneDesensitization;
import com.github.desensitization.StringDesensitization; import java.util.ArrayList;
import java.util.List; /**
* @author EalenXie create on 2021/3/18 10:07
* 此Converter提供支持日志脱敏
* 1. 编写此LogbackDesensitizeConverter
* 2. 正则脱敏 手机号/邮箱/身份证
*/
public class LogbackDesensitizeConverter extends ClassicConverter { protected static final List<StringDesensitization> DESENSITIZATION_LIST = new ArrayList<>(); static {
// 手机号脱敏
DESENSITIZATION_LIST.add(new PhoneDesensitization());
// 邮箱脱敏
DESENSITIZATION_LIST.add(new EmailDesensitization());
// 身份证脱敏
DESENSITIZATION_LIST.add(new IDCardDesensitization());
} @Override
public String convert(ILoggingEvent event) {
String content = event.getMessage();
try {
for (StringDesensitization desensitization : DESENSITIZATION_LIST) {
content = desensitization.desensitize(content);
}
} catch (Exception e) {
// ig
}
return content;
}
}
2. 启动类为PatternLayout的静态变量defaultConverterMap新增此自定义转换器

import ch.qos.logback.classic.PatternLayout;
import com.github.filter.LogbackDesensitizeConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /**
* @author EalenXie create on 2020/11/24 14:16
*/
@EnableDiscoveryClient
@SpringBootApplication
public class ApiGatewayApplication {
public static void main(String[] args) {
// 日志处理方案 新增一个Logback的日志脱敏转换器
PatternLayout.defaultConverterMap.put("m", LogbackDesensitizeConverter.class.getName());
SpringApplication.run(ApiGatewayApplication.class, args);
}
}

启动后可以看到日志脱敏效果。

利用Jackson序列化实现数据脱敏的更多相关文章

  1. Java下利用Jackson进行JSON解析和序列化

    Java下利用Jackson进行JSON解析和序列化   Java下常见的Json类库有Gson.JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行 ...

  2. Jackson序列化和反序列化Json数据完整示例

    Jackson序列化和反序列化Json数据 Web技术发展的今天,Json和XML已经成为了web数据的事实标准,然而这种格式化的数据手工解析又非常麻烦,软件工程界永远不缺少工具,每当有需求的时候就会 ...

  3. spring boot 是如何利用jackson进行序列化的?

    接上一篇:spring boot 是如何利用jackson进行反序列化的? @RestController public class HelloController { @RequestMapping ...

  4. 在Springboot + Mybaitis-plus 项目中利用Jackson实现json对java多态的(反)序列化

    Jackson允许配置多态类型处理,当JSON面对的转换对象是一个接口.抽象类或者一个基类的时候,可以通过一定配置实现JSON的转换.在实际项目中,Controller层接收入参以及在Dao层将对象以 ...

  5. jackson序列化与反序列化的应用实践

    jackson序列化与反序列化的应用实践 源码地址: https://github.com/zhouweixin/serializable 1 相关概念 序列化: 把对象转换为字节序列的过程称为对象的 ...

  6. Android剪切板传递数据传递序列化对象数据

    一.剪切板的使用介绍 1. 剪切板对象的创建 使用剪切板会用到,ClipboardManager对象,这个对像的创建不可以使用构造方法,主要是由于没有提供public的构造函数(单例模式),需要使用A ...

  7. Jackson序列化实例

    参考文章 Jackson使用ContextualSerializer在序列化时获取字段注解的属性 使用BeanSerializerModifier定制jackson的自定义序列化(null值的处理) ...

  8. Struts2.5 利用Ajax将json数据传值到JSP

    AJAX +JSON=>JSP AJAX AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着 ...

  9. java 数据脱敏

    所谓数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护.在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份 ...

随机推荐

  1. Javascript - Vue - webpack中的axios

    导入axios import Vue from "vue";import axios from "axios";import { get } from &quo ...

  2. JavaWeb学习总结——使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  3. 关于MYSQL5.7:Access denied for user 'root'@'localhost' (using password:YES)解决

    这一类解决要提供远程服务,需要进入mysql的my.ini文件中进行修改,但是在win10系统中,my.ini不再放在MYSQL安装目录的根目录中了,需要到一类应用缓存目录中寻找MYSQL的详细配置文 ...

  4. 基于mysql的sakila数据库脚本分析

    本例是基于mysql的sakila数据库脚本的复杂查询分析,大家可以去mysql官网上下载此脚本:也可以进入我的资源页进行下载: 关系图如下: 下面是查询的案例: 1.查询某部电影的所属类别,语言 S ...

  5. SpEL表达式注入漏洞学习和回显poc研究

    目录 前言 环境 基础学习和回显实验 语法基础 回显实验 BufferedReader Scanner SpEL漏洞复现 低版本SpringBoot中IllegalStateException CVE ...

  6. Spring笔记(2)

    一.AOP简介 1.概念: 面向切面编程(Aspect-Oriented Programming),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善. ...

  7. 并发编程之:AQS源码解析

    大家好,我是小黑,一个在互联网苟且偷生的农民工. 在Java并发编程中,经常会用到锁,除了Synchronized这个JDK关键字以外,还有Lock接口下面的各种锁实现,如重入锁ReentrantLo ...

  8. 【良心保姆级教程】java手把手教你用swing写一个学生的增删改查模块

    很多刚入门的同学,不清楚如何用java.swing去开发出一个系统? 不清楚如何使用java代码去操作数据库进行增删改查一些列操作,不清楚java代码和数据库(mysql.sqlserver)之间怎么 ...

  9. TypeScript 中函数的理解?与 JavaScript 函数的区别?

    一.是什么 函数是JavaScript 应用程序的基础,帮助我们实现抽象层.模拟类.信息隐藏和模块 在TypeScript 里,虽然已经支持类.命名空间和模块,但函数仍然是主要定义行为的方式,Type ...

  10. java 使用匿名内部类实现多线程的创建

    匿名内部类的作用:简化代码 把子类继承父类,重写父类的方法,创建子类对象合一步完成 把实现类实现类接口,重写接口中的方法,创建实现类对象合成一步完成 匿名内部类的最终产物:子类/实现类对象,而这个类没 ...