java-example:masktostring
Table of Contents
MaskToStringBuilder
package com.xiaosq.common; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.Map; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; /** * @author Morgan.L * @version 1.0 * @date 2019/7/9 17:10 */ public class MaskToStringBuilder extends ReflectionToStringBuilder { public MaskToStringBuilder(Object object) { super(object); } public MaskToStringBuilder(Object object, ToStringStyle style) { super(object, style); } public MaskToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) { super(object, style, buffer); } public MaskToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass, boolean outputTransients, boolean outputStatics) { super(object, style, buffer, reflectUpToClass, outputTransients, outputStatics); } @Override protected Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException { for (Annotation annotation : field.getDeclaredAnnotations()) { if (annotation instanceof SensitiveF && field.get(this.getObject()) != null) { SensitiveF.Type type = ((SensitiveF) annotation).type(); if (String.class.equals(field.get(this.getObject()).getClass())) { String fieldValue = (String) field.get(this.getObject()); return MaskUtil.doMask(type, fieldValue); //注意在使用的时候,List中必须是String,而不能是其他对象,不然会抛错 } else if (field.get(this.getObject()) instanceof Iterable) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append('['); boolean appended = false; for (String fieldValue : (Iterable<String>) field.get(this.getObject())) { if (appended) { stringBuilder.append(','); } stringBuilder.append(MaskUtil.doMask(type, fieldValue)); appended = true; } stringBuilder.append(']'); return stringBuilder.toString(); //注意在使用的时候,Map的key或者value不是String的时候就不做任何掩码操作 } else if (field.get(this.getObject()) instanceof Map) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append('{'); boolean appended = false; for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) field.get(this.getObject())).entrySet()) { if (appended) { stringBuilder.append(','); } if (entry.getKey() != null && entry.getKey() instanceof String) { String fieldValue = (String) entry.getKey(); stringBuilder.append(MaskUtil.doMask(type, fieldValue)); } else { stringBuilder.append((String) entry.getKey()); } stringBuilder.append('='); if (entry.getValue() != null && entry.getValue() instanceof String) { String fieldValue = (String) entry.getValue(); stringBuilder.append(MaskUtil.doMask(type, fieldValue)); } else { stringBuilder.append((String) entry.getValue()); } appended = true; } stringBuilder.append('}'); return stringBuilder.toString(); } } } return super.getValue(field); } }
SensitiveF
package com.xiaosq.common; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author Morgan.L * @version 1.0 * @date 4/9/2020 4:15 PM */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER}) public @interface SensitiveF { enum Type {PhoneNo, Password, IdNo, BankCardNo, RealName} Type type(); }
MaskUtil
package com.xiaosq.common; import com.spcredit.core.util.SensitiveF; import org.apache.commons.lang3.StringUtils; public class MaskUtil { private static int[] generateMaskRule(SensitiveF.Type type, String fieldValue) { //第一个表示前面需显示的长度 prefixShowLength,第二表示后面需显示的长度 suffixShowLength //默认全部掩码,所以两个值都是0 int[] result = {0, 0}; if (SensitiveF.Type.PhoneNo.equals(type) || SensitiveF.Type.IdNo.equals(type) || SensitiveF.Type.BankCardNo.equals(type)) { result[0] = 4; result[1] = 4; } else if (SensitiveF.Type.RealName.equals(type)) { if (StringUtils.isNotBlank(fieldValue)) { if (fieldValue.length() > 2) { result[0] = 1; result[1] = 1; } else { result[0] = 1; result[1] = 0; } } } else { //没有写SensitiveField.Type.Password的判断,因为安全从严的角度:默认全部掩码。 } return result; } /** * liaowenyue:此方法只用于掩码中间字符。如果要掩码两边的字符,请重新加方法,或者有其他规则的话 * fieldValue 需要掩码的字段的值 * prefixShowLength 前面需要显示的字符数 * type 敏感数据类型 */ public static String doMask(SensitiveF.Type type, String fieldValue) { int[] maskRule = generateMaskRule(type, fieldValue); String maskStr = "*"; //默认用 * 填充字符。 if (StringUtils.isBlank(fieldValue)) { return fieldValue; } int showLength = maskRule[0] + maskRule[1]; if (showLength < fieldValue.length()) { StringBuilder sb = new StringBuilder(); for (int j = 0; j < fieldValue.length(); j++) { if (j < maskRule[0]) { sb.append(fieldValue.charAt(j)); continue; } if (j > (fieldValue.length() - 1 - maskRule[1])) { sb.append(fieldValue.charAt(j)); continue; } sb.append(maskStr); } return sb.toString(); } else { return fieldValue; } } }
java-example/masktostring.txt · Last modified: 2021/12/20 09:24 by morgan0329