【工作笔记】Springboot一个比较通用的数据脱敏处理办法

  背景

        个人信息中的手机号、邮箱等属于敏感数据,其中手机号需要加密存储,邮箱可以直接存储但是在获取和展示时要做脱敏处理;

        针对此类敏感数据, 介绍一种比较通用的脱敏方法。


基于注解

        1. 定义DataMask注解

        

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DataMask {
    DataMaskEnum value() default DataMaskEnum.NO_MASK;
}

        2. 定义DataMaskOperation接口

public interface DataMaskOperation {
    String mask(String content);
}

        3. 定义DataMaskEnum敏感数据类型枚举

public enum DataMaskEnum {

    NO_MASK(str -> str),

    PHONE_MASK(phone -> {
        return phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }),

    EMAIL_MASK(email -> {
        return email.replaceAll("(\\w?)(\\w+)(\\w)(@\\w+\\.[a-z]+(\\.[a-z]+)?)", "$1****$3$4");
    });

    private final DataMaskOperation operation;

    DataMaskEnum(DataMaskOperation operation) {
        this.operation = operation;
    }

    public DataMaskOperation operation() {
        return this.operation;
    }

}

        4. 定义ValueDensitizeFilter

public class ValueDesensitizeFilter implements ValueFilter {
    private final Map<Class<?>, Map<String, DataMask>> map = new ConcurrentHashMap<>();

    @Override
    public Object process(Object object, String name, Object value) {
        if (ObjectUtils.isEmpty(value) || !(value instanceof String) || object instanceof Map || object instanceof Collection) {
            return value;
        }
        if (!map.containsKey(object.getClass())) {
            setFields(object.getClass());
        }
        Map<String, DataMask> stringDataMaskingMap = map.get(object.getClass());
        if (stringDataMaskingMap == null || stringDataMaskingMap.isEmpty()) {
            return value;
        }

        DataMask dataMask = stringDataMaskingMap.get(name);
        if (dataMask != null) {
            return dataMask.value().operation().mask((String) value);
        }
        return value;

    }

    private void setFields(Class<?> clazz) {
        Field[] declaredFields = clazz.getDeclaredFields();
        Map<String, DataMask> fieldMap = new ConcurrentHashMap<>();
        if (declaredFields != null && declaredFields.length > 0) {
            for (Field field : declaredFields) {
                String name = field.getName();
                DataMask dataMask = field.getAnnotation(DataMask.class);
                if (field.getType() == String.class && dataMask != null) {
                    fieldMap.put(name, dataMask);
                }
            }

        }
        map.put(clazz, fieldMap);
    }
}

        5. 注册Filter

@Configuration
@ConditionalOnClass({JSON.class}) //项目中集成fastjson时才进行配置
public class FastJsonSpringBootConfig {

	@Bean
    public HttpMessageConverters fastJsonHttpMessageConverters(){
        //定义一个convert转换消息的对象
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        //添加fastjson的配置信息,比如是否要格式化返回的json数据;
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        fastJsonConfig.setSerializeFilters(new ValueDesensitizeFilter());//添加自己写的拦截器
        //附加:处理中文乱码
        List<MediaType> fastMedisTypes = new ArrayList<MediaType>();
        fastMedisTypes.add(MediaType.APPLICATION_JSON_UTF8);
        fastConverter.setSupportedMediaTypes(fastMedisTypes);
       //日期格式化
        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        //在convert中添加配置信息
        fastConverter.setFastJsonConfig(fastJsonConfig);
        HttpMessageConverter<?> converter=fastConverter;
        return new HttpMessageConverters(converter);
    }
}

        6. 为需要脱敏的字段添加注解

 

    //邮箱
    @DataMask(DataMaskEnum.EMAIL_MASK)
    private String email;
    //手机号
    @DataMask(DataMaskEnum.PHONE_MASK)
    private String phone;

        这样在后端接口返回数据做序列化时,会自动将敏感信息脱敏;


        一些场合下,传输的数据并非Java对象,而是例如List,Map,Array此类数据,针对此类数据,可以直接指定其序列化配置,达到脱敏效果:

        SerializeConfig serializeConfig = new SerializeConfig();
        serializeConfig.addFilter(UserEntity.class, new ValueDesensitizeFilter());
        Map<String, Object> userMap = JSON.parseObject(JSON.toJSONString(userEntity, serializeConfig()), Map.class);

        这样在生成的Map中,Value值也可以脱敏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值