使用註解形式實現脫敏

引子

    最近老大想作一個日誌脫敏的需求,看了網上的一些方案都不太滿意,可是仍是借鑑了一些網上的代碼實現了該功能java

實現原理

    實現原理很簡單就是重寫了 fastjson ValueFilter.class process方法git

使用方法

    在實體上標明須要脫敏的字段json

    打印日誌時使用自定義公共脫敏方法 輸出日誌測試

    舉例    spa

        1:@SensitiveAnn(type = SensitiveTypeEnum.PHONE)    .net

        2:SensitiveInfoUtils.toJsonString(cardInfo)日誌

源碼

    https://gitee.com/shiliang_feng/codes/iqlnwjsezh53umbpag8vx88code

實現

       定義一個@interface Ann   裏面有一個自定義枚舉的屬性blog

    

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.demo.enums.SensitiveTypeEnum;

/**
 * 
 * @ClassName: SensitiveAnn
 * @Description:脫敏字段註解 
 * @author shiliang.feng
 * @date 2019年8月16日 下午5:11:20
 *
 */
@Target({ ElementType.TYPE, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface SensitiveAnn {
	SensitiveTypeEnum type();
}

       枚舉的代碼以下ip

    

public enum SensitiveTypeEnum {
	/** 身份證號碼 */
	ID_CARD,
	/** 銀行卡號 */
	BANK_CARD,
	/** 手機號碼 */
	PHONE,
	/** 名字 */
	NAME,
	/** 郵箱 */
	EMAIL

}

實現具體脫敏方法

    

/**
	 * 
	 * @Title: mobilePhone
	 * @Description: [手機號碼] 前三位,後兩位,其餘隱藏<例子:138********34>
	 * @author 1100122
	 * @date 2019年3月22日 下午7:56:10
	 * @param num
	 * @return 
	 * @throws
	 */
	public static String mobilePhone(String num) {
		if (StringUtils.isBlank(num)) {
			return "";
		}
		return StringUtils.left(num, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"), "***"));
	}

	/**
	 * 
	 * @Title: idCardNum
	 * @Description:  [身份證號] 顯示前六位,最後兩位,其餘隱藏。共計18位或者15位。<例子:152728*********62>
	 * @author 1100122
	 * @date 2019年3月22日 下午7:56:03
	 * @param num
	 * @return 
	 * @throws
	 */
	public static String idCardNum(String num) {
		if (StringUtils.isBlank(num)) {
			return "";
		}
		return StringUtils.left(num, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"), "******"));
	}

	/**
	 * 
	 * @Title: bankCard
	 * @Description:[銀行卡號] 前六位,後四位,其餘用星號隱藏每位1個星號<例子:6222600**********1234>
	 * @author 1100122
	 * @date 2019年3月22日 下午7:55:55
	 * @param cardNum
	 * @return 
	 * @throws
	 */
	public static String bankCard(String cardNum) {
		if (StringUtils.isBlank(cardNum)) {
			return "";
		}
		return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******"));
	}

	/**
	 * 
	 * @Title: desensitizeEmail
	 * @Description:[電子郵箱] 郵箱前綴僅顯示第一個字母,前綴其餘隱藏,用星號代替,@及後面的地址顯示<例子:g**@163.com>
	 * @author 1100122
	 * @date 2019年3月22日 下午7:51:29
	 * @param email
	 * @return 
	 * @throws
	 */
	public static String desensitizeEmail(String email) {
		if (StringUtils.isBlank(email)) {
			return "";
		}
		int index = StringUtils.indexOf(email, "@");
		if (index <= 1) {
			return email;
		} else {
			return StringUtils.rightPad(StringUtils.left(email, 1), index, "*").concat(StringUtils.mid(email, index, StringUtils.length(email)));
		}
	}

	/**
	 * 
	 * @Title: desensitizeName
	 * @Description: [中文姓名] 只顯示第一個漢字,其餘隱藏爲2個星號<例子:李**>
	 * @author 1100122
	 * @date 2019年3月22日 下午7:51:37
	 * @param fullName
	 * @return 
	 * @throws
	 */
	private static final Object desensitizeName(String fullName) {
		if (StringUtils.isBlank(fullName)) {
			return "";
		}
		String name = StringUtils.left(fullName, 1);
		return StringUtils.rightPad(name, StringUtils.length(fullName), "*");
	}

定義一個總入口

    

/**
	 * 
	 * @Title: toJsonString
	 * @Description: 日誌輸出
	 * @author shiliang.feng
	 * @date 2019年8月16日 下午2:25:10
	 * @param object
	 * @return
	 */
	public static String toJsonString(Object object) {
		return JSON.toJSONString(object, getValueFilter());
	}

重寫ValueFilter.process方法

/**
	 * 
	 * @Title: getValueFilter
	 * @Description: 日誌脫敏主方法
	 * @author shiliang.feng
	 * @date 2019年8月16日 下午2:25:28
	 * @return
	 */
	private static final ValueFilter getValueFilter() {
		return (Object obj, String key, Object value) -> {
			try {
				SensitiveAnn annotation = obj.getClass().getDeclaredField(key).getAnnotation(SensitiveAnn.class);
				if (null != annotation && value instanceof String) {
					String strVal = (String) value;
					if (StringUtils.isNotBlank(strVal)) {
						switch (annotation.type()) {
						case PHONE:
							return mobilePhone(strVal);
						case ID_CARD:
							return idCardNum(strVal);
						case BANK_CARD:
							return bankCard(strVal);
						case NAME:
							return desensitizeName(strVal);
						case EMAIL:
							return desensitizeEmail(strVal);
						default:
							break;
						}
					}
				}
			} catch (NoSuchFieldException | SecurityException e) {
			}
			return value;
		};
	}

測試一下

public static void main(String[] args) {
		CardInfo cardInfo = new CardInfo();
		cardInfo.setCardId("6228480402564890018");
		cardInfo.setName("馮小明");
		cardInfo.setPhone("18699999999");
		cardInfo.setBank("463553564656545646");
		System.out.println(SensitiveInfoUtils.toJsonString(cardInfo));
		System.out.println(JSON.toJSONString(cardInfo));
	}

結果以下

相關文章
相關標籤/搜索