User Tools

Site Tools


java-example:masktostring

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
java-example:masktostring [2021/12/20 09:13] – created morgan0329java-example:masktostring [2021/12/20 09:24] (current) – [ValidationF] morgan0329
Line 1: Line 1:
 +====== MaskToStringBuilder ======
 +<code java>
 +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);
 +    }
 +}
 +
 +</code>
 +
 +====== SensitiveF ======
 +<code java>
 +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();
 +}
 +</code>
 +
 +
 +
 +====== MaskUtil ======
 +<code java>
 +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;
 +        }
 +    }
 +}
 +</code>

Except where otherwise noted, content on this wiki is licensed under the following license: 沪ICP备12046235号-2
Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki