自学内容网 自学内容网

SpringBoot中通过自定义Jackson注解实现接口返回数据脱敏

1、自定义Jackson注解

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 定义一个敏感信息注解,用于标记需要进行脱敏处理的字段。
 * 该注解会告知序列化器使用指定的脱敏策略对字段进行处理。
 */
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时有效
@Target(ElementType.FIELD) // 注解适用于字段
@JacksonAnnotationsInside // 将注解应用到字段的内部配置中
@JsonSerialize(using = SensitiveJsonSerializer.class) // 指定使用SensitiveJsonSerializer进行序列化
public @interface Sensitive {
    /**
     * 脱敏策略枚举,指定对待敏感字段使用的脱敏策略。
     *
     * @return SensitiveStrategy枚举值,定义了脱敏处理的方式。
     */
    SensitiveStrategy strategy();
}

2 指定脱敏策略,这个规则根据业务具体需求去制定

import java.util.function.Function;

/**
 * 脱敏策略,枚举类,针对不同的数据定制特定的策略
 */
public enum SensitiveStrategy {
    /**
     * 用户名脱敏策略
     * 将除第一个字符和最后一个字符外的字符替换为星号
     */
    USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
    /**
     * 身份证脱敏策略
     * 将身份证号码的中间10位数字替换为星号
     */
    ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1****$2")),
    /**
     * 手机号脱敏策略
     * 将手机号码中间4位数字替换为星号
     */
    PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
    /**
     * 地址脱敏策略
     * 将地址中的第四个和倒数第四个字符中间的部分替换为星号
     */
    ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}", "$1****$2****"));

    // 脱敏函数,接受一个字符串并返回脱敏后的字符串
    private final Function<String, String> desensitizer;

    /**
     * 构造函数,为每个脱敏策略初始化脱敏函数
     * @param desensitizer 脱敏函数
     */
    SensitiveStrategy(Function<String, String> desensitizer) {
        this.desensitizer = desensitizer;
    }

    /**
     * 获取当前策略的脱敏函数
     * @return 脱敏函数
     */
    public Function<String, String> desensitizer() {
        return desensitizer;
    }
}

3 定制JSON序列化实现

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import java.io.IOException;
import java.util.Objects;

/**
 * 用于处理敏感信息序列化的自定义JsonSerializer实现。
 * 通过应用指定的脱敏策略,将待序列化的字符串进行脱敏处理。
 */
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
    private SensitiveStrategy strategy; // 脱敏策略

    /**
     * 序列化方法,将字符串根据脱敏策略进行处理后,写入JsonGenerator。
     *
     * @param value 需要序列化的字符串
     * @param gen JsonGenerator,用于输出处理后的字符串
     * @param serializers SerializerProvider,提供序列化器实例
     * @throws IOException 如果在序列化过程中发生IO异常
     */
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws
            IOException {
        gen.writeString(strategy.desensitizer().apply(value));
    }

    /**
     * 根据属性上的Sensitive注解,选择合适的脱敏策略。
     *
     * @param prov SerializerProvider,提供序列化器实例
     * @param property BeanProperty,当前处理的属性
     * @return JsonSerializer,根据情况可能返回本实例或寻找合适的值序列化器
     * @throws JsonMappingException 如果在处理注解时发生错误
     */
    @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 对需要脱敏的字段添加注解,并指定脱敏策略,注意:类型需要是String类型,如下

@Sensitive(strategy = SensitiveStrategy.PHONE)
private String phone;

效果如下:
"185****3654"


原文地址:https://blog.csdn.net/qq_41712271/article/details/137817315

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!