使用自定义Json注解实现输出日志字段脱敏

以下是使用自定义Json注解实现输出日志字段脱敏的完整攻略。

什么是Json注解

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写。在Java应用程序中,我们通常使用Jackson或者Gson等库将Java对象序列化为JSON格式。而Json注解则是在Java对象中添加特定标记以控制序列化和反序列化过程的一种方式。

为什么需要Json注解

在某些情况下,我们需要对输出的字段进行脱敏,比如手机号、身份证号等敏感信息。如果我们直接将对象序列化为JSON格式输出,这些敏感信息就暴露给了外界。因此,有必要使用Json注解对输出的字段进行脱敏。

如何使用自定义Json注解实现输出日志字段脱敏

  1. 定义自定义注解

我们先定义一个自定义注解 @SensitiveProperty,用于标记需要脱敏的字段。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SensitiveProperty {
}
  1. 定义Jackson的自定义序列化程序

我们定义一个SensitivePropertySerializer用于实现自定义的序列化逻辑。该序列化程序会在序列化时遍历Java对象的所有属性,并判断哪些属性被标记为@SensitiveProperty,将其进行脱敏处理。

public class SensitivePropertySerializer extends JsonSerializer<Object> {

    private static final String SENSITIVE_MASK = "******";

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        PropertyFilter filter = new SimpleBeanPropertyFilter() {
            @Override
            public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception {
                if (!writer.isFiltered()) {
                    if (writer.getAnnotation(SensitiveProperty.class) != null) {
                        jgen.writeStringField(writer.getName(), SENSITIVE_MASK);
                    } else {
                        writer.serializeAsField(pojo, jgen, provider);
                    }
                }
            }
        };

        ObjectMapper mapper = new ObjectMapper();
        mapper.setFilterProvider(new SimpleFilterProvider().addFilter("myFilter", filter));
        mapper.writerWithDefaultPrettyPrinter().writeValue(gen, value);
        gen.writeEndObject();
    }
}

  1. 定义Java对象

在Java对象中添加自定义注解@SensitiveProperty来标记需要脱敏的属性。

public class User {
    private int id;
    private String name;
    private String phone;
    private String address;

    @SensitiveProperty
    private String idCard;

    // getter和setter方法省略
}

  1. 序列化Java对象

我们使用Jackson将Java对象序列化为JSON格式,并实现脱敏。

public class Main {
    public static void main(String[] args) {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        user.setPhone("18312345678");
        user.setAddress("北京市海淀区");
        user.setIdCard("110101199001011234");

        SimpleFilterProvider filterProvider = new SimpleFilterProvider();
        filterProvider.addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept("id", "name", "phone", "address", "idCard"));

        ObjectMapper mapper = new ObjectMapper();
        mapper.setFilterProvider(filterProvider);
        try {
            String jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
            System.out.println(jsonString);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

执行以上代码,控制台输出的JSON字符串如下所示:

{
  "id" : 1,
  "name" : "张三",
  "phone" : "18312345678",
  "address" : "北京市海淀区",
  "idCard" : "******"
}
  1. 使用自定义注解实现多种脱敏方式

除了像上面的例子一样使用固定的脱敏字符串,有时我们可能需要根据需求进行不同方式的脱敏。此时,我们可以在@SensitiveProperty注解中添加一个脱敏类型的参数。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SensitiveProperty {
    String type() default "default";
}

在序列化程序中判断注解中的脱敏类型字段,进行不同的脱敏方式。

public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
    // ...
    String rawValue = String.valueOf(propertyValue);
    if ("default".equals(sensitiveType)) {
        jgen.writeStringField(name, SENSITIVE_MASK);
    } else if ("name".equals(sensitiveType)) {
        jgen.writeStringField(name, rawValue.substring(0, 1) + SENSITIVE_MASK);
    } else if ("phone".equals(sensitiveType)) {
        jgen.writeStringField(name, rawValue.substring(0, 3) + SENSITIVE_MASK + rawValue.substring(7));
    } else if ("idCard".equals(sensitiveType)) {
        jgen.writeStringField(name, rawValue.substring(0, 4) + SENSITIVE_MASK + rawValue.substring(14));
    } else {
        writer.serializeAsField(pojo, jgen, provider);
    }
}

我们可以使用上面定义的注解@SensitiveProperty来标记需要脱敏的字段以及不同的脱敏方式。

public class User {
    private int id;

    @SensitiveProperty(type = "name")
    private String name;

    @SensitiveProperty(type = "phone")
    private String phone;

    private String address;

    @SensitiveProperty(type = "idCard")
    private String idCard;

    // getter和setter方法省略
}

执行以上代码,输出的JSON字符串如下所示:

{
  "id" : 1,
  "name" : "张******",
  "phone" : "183****5678",
  "address" : "北京市海淀区",
  "idCard" : "1101******1234"
}

这样,我们利用自定义注解@SensitiveProperty和Jackson的自定义序列化程序就实现了输出日志字段脱敏的功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用自定义Json注解实现输出日志字段脱敏 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • maven assembly打包生成Java应用启动脚本bat和sh的方法

    Maven是一个流行的Java项目管理和构建工具,它可以自动处理依赖关系和构建过程。 Maven Assembly插件提供了将Java应用程序打包成一个可执行的JAR文件并创建用于启动应用程序的脚本的功能。本教程将介绍如何使用Maven Assembly插件打包Java应用程序并生成启动脚本。 安装Maven 首先,您需要安装Maven。您可以从Maven官…

    Java 2023年6月2日
    00
  • SpringBoot浅析安全管理之Spring Security配置

    SpringBoot浅析安全管理之Spring Security配置 Spring Security是一个强大的安全框架,可以为Spring应用程序提供身份验证、授权、加密和会话管理等功能。在本文中,我们将介绍如何使用Spring Security配置安全管理,并提供两个示例。 步骤一:添加Spring Security依赖 我们需要在pom.xml文件中添…

    Java 2023年5月15日
    00
  • springboot 集成dubbo的步骤详解

    下面是关于“Spring Boot集成Dubbo的步骤详解”的完整攻略,包含了以下内容: 环境搭建 引入依赖 编写Dubbo服务接口和实现类 配置Dubbo的服务提供者和消费者 演示实例 环境搭建 在开始前必须确定以下工具: 使用Java 1.8或以上版本 下载并安装ZooKeeper 下载Dubbo 引入依赖 使用Maven管理依赖,导入以下依赖: &lt…

    Java 2023年5月19日
    00
  • jsp有两个按钮来控制Timer的开始和结束方法

    首先,我们需要明确以下几点: JSP是Java Web开发中的一种技术,可以用来生成动态网页; Timer类是Java中的一个计时器类,可以用来定时执行某些操作。 有了以上的基础知识,我们就可以来讲解如何使用JSP和Timer来实现在网页上控制定时器的开始和结束方法了。 第一步,我们需要在JSP页面中创建两个按钮,一个用来启动计时器,一个用来停止计时器。可以…

    Java 2023年6月15日
    00
  • SpringBoot接口返回结果封装方法实例详解

    SpringBoot接口返回结果封装方法实例详解 在SpringBoot中,我们可以使用接口返回结果封装方法来统一处理接口返回结果。本文将详细讲解SpringBoot接口返回结果封装方法实例的完整攻略,并提供两个示例。 1. 接口返回结果封装方法 在SpringBoot中,我们可以使用接口返回结果封装方法来统一处理接口返回结果。以下是接口返回结果封装方法的基…

    Java 2023年5月15日
    00
  • Java Spring Boot 集成Zookeeper

    Java Spring Boot 集成 Zookeeper 完整攻略 什么是 Zookeeper ZooKeeper 是一个分布式协调服务,能够在分布式系统中提供一致性,可靠性,易用性的功能,使得分布式应用的开发和维护变得更加容易。 ZooKeeper 作为独立的服务来运行,但常常与分布式应用程序一起使用,作为分布式应用程序的一部分运行。 集成 Zookee…

    Java 2023年5月19日
    00
  • JAVA基础之控制台输入输出的实例代码

    JAVA基础之控制台输入输出的实例代码 本文将介绍JAVA语言中,如何利用控制台进行输入输出操作。首先需要理解Java标准I/O流的概念,Java的I/O流分为两种:字节流和字符流。字节流以字节为单位进行操作,字符流以字符为单位进行操作。在控制台输入输出中,一般使用字符流,使用InputStreamReader和OutputStreamWriter将字节流转…

    Java 2023年5月30日
    00
  • Java中关于控制台读取数字或字符串的方法

    Java中关于控制台读取数字或字符串的方法有以下几种: 使用Scanner类读取控制台输入 Scanner是Java中的一个类,可以用于读取控制台输入。通过Scanner对象可以方便地从控制台读取数字或字符串。Scanner类位于java.util包中,在使用前需要导入该包。 import java.util.Scanner; public class Co…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部