利用Jackson序列化实现数据脱敏
几天前使用了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序列化实现数据脱敏的更多相关文章
- Java下利用Jackson进行JSON解析和序列化
Java下利用Jackson进行JSON解析和序列化 Java下常见的Json类库有Gson.JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行 ...
- Jackson序列化和反序列化Json数据完整示例
Jackson序列化和反序列化Json数据 Web技术发展的今天,Json和XML已经成为了web数据的事实标准,然而这种格式化的数据手工解析又非常麻烦,软件工程界永远不缺少工具,每当有需求的时候就会 ...
- spring boot 是如何利用jackson进行序列化的?
接上一篇:spring boot 是如何利用jackson进行反序列化的? @RestController public class HelloController { @RequestMapping ...
- 在Springboot + Mybaitis-plus 项目中利用Jackson实现json对java多态的(反)序列化
Jackson允许配置多态类型处理,当JSON面对的转换对象是一个接口.抽象类或者一个基类的时候,可以通过一定配置实现JSON的转换.在实际项目中,Controller层接收入参以及在Dao层将对象以 ...
- jackson序列化与反序列化的应用实践
jackson序列化与反序列化的应用实践 源码地址: https://github.com/zhouweixin/serializable 1 相关概念 序列化: 把对象转换为字节序列的过程称为对象的 ...
- Android剪切板传递数据传递序列化对象数据
一.剪切板的使用介绍 1. 剪切板对象的创建 使用剪切板会用到,ClipboardManager对象,这个对像的创建不可以使用构造方法,主要是由于没有提供public的构造函数(单例模式),需要使用A ...
- Jackson序列化实例
参考文章 Jackson使用ContextualSerializer在序列化时获取字段注解的属性 使用BeanSerializerModifier定制jackson的自定义序列化(null值的处理) ...
- Struts2.5 利用Ajax将json数据传值到JSP
AJAX +JSON=>JSP AJAX AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着 ...
- java 数据脱敏
所谓数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护.在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份 ...
随机推荐
- BootStrap学习代码
要为毕设做准备了! 哎,毕设前台得自己来,所以打算学学bootstrap,把学习的代码放到码云上面了,使用HbuilderX来写,界面友好,适合我这种前端小白- 第一天就感受到了写html快捷键的强大 ...
- 寻找最短路径Dijkstra算法
1 /** 2 * 1.对于T中的每个顶点u,找到u的具有最小权重的连接边.所有到u的连接边都存储在queues.get(u)中.queues.get(u).peek()返回拥有最小权值 3 * 的连 ...
- linux 常用命令(一)——查看硬盘空间-内存-线程的cpu负载-线程内存
系统参数检查: df -h [enter] 检查硬盘空间 TIP: 使用 man df 可查看该命令使用说明 ; q 退出. free检查内存使用情况: free [enter] TIP: 使用 ma ...
- OpenCV 传统分割测试
github官网源文件:https://github.com/opencv/opencv/tree/master/samples/python 最好是先克隆整个仓库下来,再测试里面的:floodfil ...
- java变量类型和常量类型
变量类型 局部变量 实例变量 类变量 public class 变量类型 { //属性:变量 //必须先定义再使用,并初始化 //布尔型:默认值为false //3. 类变量(静态变量) static ...
- .Net Core配置Configuration源码研究
最近又研究了一下.NetCore配置选项的源码实现,又学习到了不少东西.这篇文章先写一下IConfiguration的学习成果,Options的后面补上 核心类 ConfigurationBuilde ...
- 解决win10 cmd运行python弹出windows应用商店下python应用程序
方法一: 1.我一开始下载完python后,忘记下载到哪个位置,在win10底下输入框搜索python,点击打开文件所在位置,所在位置是python快捷键的位置,直接复制进行环境配置 配置完环境变量后 ...
- Linux从头学11:理解了这三个概念,才能彻底理解任务管理和任务切换
作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...
- Django——实现最基础的评论功能(只有一级评论)
我对评论功能的理解: --------(1)数据库建一个评论的表 --------(2)前端建一个提交评论的form表单 --------(3)表单提交评论内容后写入到数据库评论表中 -------- ...
- uniapp 获取用户手机号
参考资料: 微信小程序官方文档 uniapp开发微信小程序获取用户手机号 页面增加一个按钮 <button open-type="getPhoneNumber" @getph ...