背景: 在日志输出的时候,有时会输出一些用户的敏感信息,如手机号,身份证号,银行卡号等,现需要对这些信息在日志输出的时候进行脱敏处理
思路: 使用fastjson的ValueFilter对带有自定义注解的字段进行过滤
/**
* 敏感信息类型
*
* @author worstEzreal
* @version V1.0.0
* @date 2017/7/19
*/
public enum SensitiveType {
ID_CARD,
BANK_CARD,
PHONE
}
/**
* 脱敏字段注解
*
* @author worstEzreal
* @version V1.0.0
* @date 2017/7/19
*/
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SensitiveInfo {
SensitiveType type();
}
/**
* 日志敏感信息脱敏工具
*
* @author worstEzreal
* @version V1.0.0
* @date 2017/7/19
*/
public class SensitiveInfoUtils {
public static String toJsonString(Object object) {
return JSON.toJSONString(object, getValueFilter());
}
private static String desensitizePhoneOrIdCard(String num) {
if (StringUtils.isBlank(num)) {
return "";
}
return StringUtils.left(num, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*"), "***"));
}
private static String desensitizeBankCard(String cardNum) {
if (StringUtils.isBlank(cardNum)) {
return "";
}
return StringUtils.left(cardNum, 4).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "****"));
}
private static final ValueFilter getValueFilter() {
return new ValueFilter() {
@Override
public Object process(Object obj, String key, Object value) {//obj-对象 key-字段名 value-字段值
try {
Field field = obj.getClass().getDeclaredField(key);
SensitiveInfo annotation = field.getAnnotation(SensitiveInfo.class);
if (null != annotation && value instanceof String) {
String strVal = (String) value;
if (StringUtils.isNotBlank(strVal)) {
switch (annotation.type()) {
case PHONE:
return desensitizePhoneOrIdCard(strVal);
case ID_CARD:
return desensitizePhoneOrIdCard(strVal);
case BANK_CARD:
return desensitizeBankCard(strVal);
default:
break;
}
}
}
} catch (NoSuchFieldException e) {
//找不到的field对功能没有影响,空处理
}
return value;
}
};
}
public static void main(String[] args) {
CardInfo cardInfo = new CardInfo();
cardInfo.setId("11111111111111111");
cardInfo.setCardId("6228480402564890018");
System.out.println(SensitiveInfoUtils.toJsonString(cardInfo));
}
}
附CardInfo类:
public class CardInfo {
private String userId;
private String name;
@SensitiveInfo(type = SensitiveType.ID_CARD)
private String certId;
@SensitiveInfo(type = SensitiveType.BANK_CARD)
private String cardId;
private String bank;
private String phone;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCertId() {
return certId;
}
public void setCertId(String certId) {
this.certId = certId;
}
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public String getBank() {
return bank;
}
public void setBank(String bank) {
this.bank = bank;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}