数据脱敏实战:使用Hutool工具类快速实现敏感信息保护
数据脱敏实战:使用Hutool工具类快速实现敏感信息保护
数据脱敏是保护敏感信息的重要手段,在实际开发中经常需要对用户信息等敏感数据进行处理。本文将详细介绍如何使用Hutool工具类在Java项目中实现数据脱敏,包括工具类的使用、注解方式的接入以及在Excel导出中的应用。
1. 数据脱敏定义
数据脱敏,指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。因为在真正的生产环境中,很多数据是不能直接返回,但是我们工作的时候可能经常性的需要返回一些用户信息,而用户信息里面就包括了一些敏感信息,所以就需要脱敏。
此篇文章将介绍如何使用Hutool工具类进行数据脱敏。
2. Hutool 工具介绍
Hutool是一个非常实用的Java工具包,提供了丰富的工具类来简化开发工作。其中,数据脱敏工具类可以帮助开发者快速实现敏感信息的保护。
3. 数据脱敏接入WMS项目
在WMS项目中,特别是在用户管理列表中,经常需要对用户信息进行数据脱敏处理。通过Hutool工具类,可以很方便地实现这一功能。
4. 业务接入
假设我们已经导入了Hutool工具类,可以直接使用其提供的数据脱敏功能。但是,直接在业务代码中使用工具类会使得业务代码与数据脱敏逻辑耦合在一起,不利于代码的维护和扩展。
5. SpringBoot使用注解方式接入
为了更好地解耦业务逻辑和数据脱敏处理,我们可以使用注解的方式。下面是一个自定义注解的实现示例:
import com.beiyou.config.SensitiveInfoSerializer;
import com.beiyou.enums.DesensitizationType;
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;
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveInfoSerializer.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Desensitization {
DesensitizationType type() default DesensitizationType.DEFAULT;
/**
* 前置不需要打码的长度
*/
int prefixLen() default 0;
/**
* 后置不需要打码的长度
*/
int suffixLen() default 0;
/**
* 遮罩字符
*/
String maskingChar() default "*";
}
这个注解包含了以下关键点:
@JacksonAnnotationsInside
:这是一个元注解,它告诉 Jackson 解析器,这个注解应该被视为 Jackson 的一部分,也就是说 Jackson 会处理带有此注解的字段。@JsonSerialize(using = SensitiveInfoSerializer.class)
:注解用于指定如何序列化一个字段或方法。它允许你指定一个自定义的序列化器类,Jackson 将使用这个类来序列化带有该注解的字段或方法返回的结果。SensitiveInfoSerializer
:这是一个自定义的序列化器,用于实现具体的脱敏逻辑。
脱敏类型
Hutool提供了多种脱敏类型,可以通过枚举来选择:
public enum DesensitizationType {
// 自定义规则
CUSTOMIZE_RULE, // 默认的
DEFAULT, //用户id
USER_ID, //中文名
CHINESE_NAME, //身份证号
ID_CARD, //座机号
FIXED_PHONE, //手机号
MOBILE_PHONE, //地址
ADDRESS, //电子邮件
EMAIL, //密码
PASSWORD, //中国大陆车牌,包含普通车辆、新能源车辆
CAR_LICENSE, //银行卡
BANK_CARD
}
序列化工具的代码
下面是具体的序列化器实现:
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.beiyou.annotation.Desensitization;
import com.beiyou.enums.DesensitizationType;
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 java.io.IOException;
public class SensitiveInfoSerializer extends JsonSerializer<String> implements ContextualSerializer {
private boolean useMasking = false;
private DesensitizationType type;
private int prefixLen;
private int suffixLen;
private String maskingChar;
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (useMasking && value != null) {
switch (type) {
case CUSTOMIZE_RULE:
gen.writeString(StrUtil.hide(value, prefixLen, suffixLen));
break;
case DEFAULT:
gen.writeString(value);
break;
case CHINESE_NAME:
gen.writeString(DesensitizedUtil.chineseName(value));
break;
case ID_CARD:
gen.writeString(DesensitizedUtil.idCardNum(value, prefixLen, suffixLen));
break;
case FIXED_PHONE:
gen.writeString(DesensitizedUtil.fixedPhone(value));
break;
case MOBILE_PHONE:
gen.writeString(DesensitizedUtil.mobilePhone(value));
break;
case ADDRESS:
gen.writeString(DesensitizedUtil.address(value, prefixLen));
break;
case EMAIL:
gen.writeString(DesensitizedUtil.email(value));
break;
case PASSWORD:
gen.writeString(DesensitizedUtil.password(value));
break;
case CAR_LICENSE:
gen.writeString(DesensitizedUtil.carLicense(value));
break;
case BANK_CARD:
gen.writeString(DesensitizedUtil.bankCard(value));
break;
default:
gen.writeString(value);
}
} else {
gen.writeString(value);
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
if (property != null) {
Desensitization desensitization = property.getAnnotation(Desensitization.class);
if (desensitization != null) {
this.type = desensitization.type();
this.prefixLen = desensitization.prefixLen();
this.suffixLen = desensitization.suffixLen();
this.maskingChar = desensitization.maskingChar();
useMasking = true;
}
}
return this;
}
}
这个序列化器会根据注解中的规则和参数来决定如何脱敏该字段的内容。脱敏后的结果将被写入 JSON 数据中,从而保护了敏感信息不被泄露。
直接使用
在实体类中可以直接使用注解:
public class User {
@Desensitization(type = DesensitizationType.MOBILE_PHONE)
private String mobilePhone;
// getters and setters
}
这样,当Jackson序列化User对象时,会自动对mobilePhone字段进行脱敏处理。
6. Excel导出数据脱敏
对于Excel导出场景,由于无法使用Jackson的序列化机制,需要手动使用工具类进行数据脱敏。在数据将进行序列化之前,需要手动调用脱敏工具类对数据进行处理。