SpringBoot 敏感信息脱敏

SpringBoot 敏感信息脱敏

1、定义脱敏注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@JacksonAnnotation
public @interface Desensitization {

    /**
     * 字段脱敏策略
     * @return
     */
    DesensitizationStrategy strategy();

    /**
     * 匹配正则表达式
     * <pre>
     *     1. 手机号:regex:(\\d{3})\\d{4}(\\d{4}) ,replacement: $1****$2
     *     2. 地址:regex:(\\S{3})\\S{2}(\\S*)\\S{2},replacement:$1****$2****
     * </pre>
     * @return String
     */
    String regex() default "";

    /**
     * 替换内容
     * @return String
     */
    String replacement() default "";
}

脱敏策略

/**
 * 脱敏策略
 */
public enum DesensitizationStrategy {
    /**
     * 用户ID
     * 例如: 100 -> 0
     */
    USER_ID,
    /**
     * 中文名称
     * 如:段正淳 -> 段**
     */
    CHINESE_NAME,
    /**
     * 身份证号
     * 如:51343620000320711X -> 5***************1X
     */
    ID_CARD,
    /**
     * 座机号
     * 如:09157518479 -> 0915*****79
     */
    FIXED_PHONE,
    /**
     * 手机号
     * 如:18049531999 -> 180****1999
     */
    MOBILE_PHONE,
    /**
     * 地址:北京市海淀区马连洼街道289号
     * 北京市海淀区马********
     */
    ADDRESS,
    /**
     * 电子邮件
     * 如:duandazhi-jack@gmail.com.cn -> d*************@gmail.com.cn
     */
    EMAIL,
    /**
     * 密码
     * 如: 1234567890 -> **********
     */
    PASSWORD,
    /**
     * 中国大陆车牌,包含普通车辆、新能源车辆
     * 如:苏D40000 -> 苏D4***0
     */
    CAR_LICENSE,
    /**
     * 银行卡
     * 11011111222233333256 -> 1101 **** **** **** 3256
     */
    BANK_CARD;
}

jackson 支持注解脱敏

package com.aimilin.common.security.json;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.aimilin.common.core.annotation.Desensitization;
import com.aimilin.common.core.enums.DesensitizationStrategy;
import com.aimilin.common.core.utils.DesensitizedUtil;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 脱敏序列化
 * <pre>
 *     1、fastjson 使用,直接 JSON.toJSONString(object,new DesensitizationSerializer());
 *     2、jackson使用,com.aimilin.common.core.utils.JsonUtil#toJson(java.lang.Object)
 * </pre>
 * @author liujunguang1
 * @version V1.0
 * @date 2022/9/6 14:27
 */
public class DesensitizationSerializer extends JsonSerializer<Object> implements ValueFilter {
    /**
     * 脱敏配置项
     */
    private Desensitization desensitization;
    /**
     * fastjson序列化缓存
     */
    private static final Map<Class<?>, Map<String,Desensitization>> map = new ConcurrentHashMap<>();

    public DesensitizationSerializer() {
    }

    public DesensitizationSerializer(Desensitization desensitization) {
        this.desensitization = desensitization;
    }

    /**
     * Method that can be called to ask implementation to serialize
     * values of type this serializer handles.
     *
     * @param value       Value to serialize; can <b>not</b> be null.
     * @param gen         Generator used to output resulting Json content
     * @param serializers Provider that can be used to get serializers for
     *                    serializing Objects value contains, if any.
     */
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if(Objects.isNull(value) || Objects.isNull(desensitization)) {
            serializers.defaultSerializeValue(value, gen);
            return;
        }
        gen.writeString(this.desensitized(value));
    }

    /**
     * 将字段信息脱敏
     * @param value 当前值
     * @return 结果
     */
    private String desensitized(Object value) {
        String valueStr = StrUtil.toStringOrNull(value);
        DesensitizationStrategy strategy = this.desensitization.strategy();
        if(Objects.nonNull(strategy)){
            return DesensitizedUtil.desensitized(valueStr, DesensitizedUtil.DesensitizedType.valueOf(strategy.name()));
        }
        if(StringUtils.isNotBlank(this.desensitization.regex())) {
            return RegExUtils.replaceAll(valueStr, this.desensitization.regex(), this.desensitization.replacement());
        }
        return valueStr;
    }


    @Override
    public Object process(Object object, String name, Object value) {
        if (null == object || StringUtils.isEmpty(name) || null == value){
            return value;
        }
        Desensitization annotation = this.getFieldDesensitization(object, name);
        if(annotation != null){
            return new DesensitizationSerializer(annotation).desensitized(value);
        }
        return value;
    }

    /**
     * 获取属性对应的Desensitization的注解
     * @param object 对象
     * @param name 属性名称
     * @return 结果
     */
    private Desensitization getFieldDesensitization(Object object, String name) {
        Class<?> key = object.getClass();
        if(map.containsKey(key)){
            return map.get(key).get(name);
        }
        Field[] fields = ReflectUtil.getFields(key);
        Map<String,Desensitization> fieldMap = new HashMap<>();
        for (Field field: fields){
            Desensitization annotation = field.getAnnotation(Desensitization.class);
            if(annotation != null) {
                fieldMap.put(field.getName(), annotation);
            }
        }
        map.put(key, fieldMap);
        return map.get(key).get(name);
    }
}

jackson Bean序列化

package com.aimilin.common.security.json;

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.aimilin.common.core.annotation.Desensitization;

import java.util.List;

/**
 * Jackson字段脱敏序列化工具
 *
 * @author liujunguang1
 * @version V1.0
 * @date 2022/9/6 17:23
 */
public class DesensitizationSerializerModifier extends BeanSerializerModifier{
    /**
     * Method called by {@link BeanSerializerFactory} with tentative set
     * of discovered properties.
     * Implementations can add, remove or replace any of passed properties.
     * <p>
     * Properties <code>List</code> passed as argument is modifiable, and returned List must
     * likewise be modifiable as it may be passed to multiple registered
     * modifiers.
     *
     * @param config 配置
     * @param beanDesc 定义
     * @param beanProperties 属性
     */
    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        for (BeanPropertyWriter beanProperty : beanProperties) {
            Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);
            if (desensitization != null) {
                beanProperty.assignSerializer(new DesensitizationSerializer(desensitization));
            }
        }
        return beanProperties;
    }
}

3 注册序列化器

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer desensitizationJackson2ObjectMapperBuilderCustomizer(){
        return jacksonObjectMapperBuilder -> {
            SimpleModule simpleModule = new SimpleModule();
            simpleModule.setSerializerModifier(new DesensitizationSerializerModifier());
            List<Module> moduleList = new ArrayList<>();
            moduleList.add(simpleModule);
		  // 支持多个配置信息 
            jacksonObjectMapperBuilder.modules(moduleList::addAll);
            jacksonObjectMapperBuilder.modules(moduleList);
        };
    }

敏感信息脱敏

由于数据转换成JSON字符串都是采用的jackson

  1. jackson 信息脱敏
    在java类中添加注解:com.jd.gxf.common.core.annotation.Desensitization
    该注解支持预定义脱敏模式与自定义脱敏格式
@Data
public class SysUserResult {

    /**
     * 主键
     */
    private Long id;
    
    /**
     * 姓名
     */
    private String name;
    
    /**
     * 邮箱
     */
    @Desensitization(strategy = DesensitizationStrategy.EMAIL)
    private String email;

    /**
     * 手机
     */
    @Desensitization(strategy = DesensitizationStrategy.MOBILE_PHONE)
    private String phone;

}
  1. Fastjson使用说明
JSON.toJsonString(sysUserResult, new DesensitizationSerializer())
SpringBoot提供了一种信息脱敏的功能。可以通过定义脱敏注解和使用注解来实现信息脱敏。\[1\]\[2\]在定义脱敏注解时,可以指定脱敏策略、匹配正则表达式和替换内容。通过使用注解,可以将脱敏注解应用到需要脱敏字段上。\[2\]在SpringBoot中,可以通过创建一个控制器类来演示信息脱敏的功能。\[2\]在这个控制器类中,可以定义一个返回脱敏数据的接口。\[2\]通过调用这个接口,可以获取到经过脱敏处理的数据。\[2\]在信息脱敏的实现中,可以使用枚举来定义不同的脱敏规则。\[3\]通过重写枚举实例的mask()方法,可以实现不同的脱敏规则。\[3\]这样,就可以根据自己的需求来进行信息脱敏操作了。 #### 引用[.reference_title] - *1* [SpringBoot 敏感信息脱敏](https://blog.csdn.net/afgasdg/article/details/126736021)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [【SpringBoot】三种常见的数据脱敏方案](https://blog.csdn.net/sco5282/article/details/126642636)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值