JavaWeb信息脱敏的实现


基于实体的注解

先定义一个基于对象的脱敏注解

/**
 * 属性脱敏注解
 *
 * @author kandw [kandw@yinhai.com]
 * @version 2019/8/28
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TaSensitive {
    /**
     * 返回脱敏字段是否带加密文本,若是设置为true,则和返回脱敏文本时同时返回本字段的RSA加密字段
     *
     * @return
     */
    boolean withEncrypt() default false;

    /**
     * 前缀预留位数
     * 比如:
     * prefixLength=3
     * private String idCard="41234560987123543"
     * 打码后为: idCard= 412**************
     */
    int prefixLength() default 0;

    /**
     * 后缀预留位数
     * 比如:
     * suffixLength=3
     * private String idCard="41234560987123543"
     * 打码后为: idCard= **************543
     */
    int suffixLength() default 0;

    /**
     * 敏感字符替换字符
     * 比如: sensitiveChar="$",(suffixLength=3);
     */
    String sensitiveChar() default "*";
}

脱敏注解实现

/**
 * 数据脱敏工具
 *
 * @author kandw [kandw@yinhai.com]
 * @version 2019/8/28
 */
public class DesensitizeUtil {

    private DesensitizeUtil() {
        //empty internal constructor
    }

    /**
     * List<object> 打码
     *
     * @param obj 需要脱敏问List集合
     * @return 返回脱敏后的数据
     */
    public static List<Object> maskListObject(List<Object> obj) {
        if (null == obj || obj.isEmpty()) {
            return Collections.emptyList();
        }
        List<Object> maskList = new ArrayList<>();
        for (Object e : obj) {
            maskObject(e);
            maskList.add(e);
        }
        return maskList;

    }

    @SuppressWarnings("unchecked")
    public static <E> E mask(E obj) {
        if (obj instanceof Collection) {
            ((Collection) obj).forEach(DesensitizeUtil::maskObject);
        } else {
            obj = maskObject(obj);
        }
        return obj;
    }

    /**
     * 字符串脱敏
     *
     * @param obj 需要脱敏的对象
     * @return 返回脱敏后的对象
     */
    public static <E> E maskObject(E obj) {
        if (null == obj) {
            return null;
        }

        Field[] declaredFields = obj.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            TaSensitive annotation = field.getAnnotation(TaSensitive.class);
            //只能对字符串脱敏
            if (null == annotation || !field.getType().equals(String.class)) {
                continue;
            }

            String value = null;
            try {
                value = (String) field.get(obj);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if (StringUtils.isEmpty(value)) {
                continue;
            }
            int suffix = annotation.suffixLength();
            int prefix = annotation.prefixLength();
            String character = annotation.sensitiveChar();
            try {
                String sensitiveStr = maskString(value, character, prefix,
                        suffix);
                //此处如果不需要可注释
                //if (annotation.withEncrypt()) {
                    field.set(obj, JsonFactory.bean2json(new TaSensitiveBean(sensitiveStr, RSAUtils.encryptWidthEncode(value), new Format(prefix, suffix))));
                //} else {
                    field.set(obj, sensitiveStr);
                //}
            } catch (IllegalAccessException | UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }


        return obj;
    }

    /**
     * 对字符串脱敏
     *
     * @param content   需要脱敏的正文
     * @param character 脱敏后字符
     * @param prefix    预留前缀(不需要脱敏的)
     * @param suffix    预留后缀(不需要脱敏的)
     * @return 脱敏后的正文
     */
    @PostMapping
    public static String maskString(String content, String character, int prefix, int suffix) {
        if (StringUtils.isEmpty(content)) {
            return "";
        }
        String replacement = produceCharacter(content.length() - prefix - suffix, character);
        String regex = "([\\s\\S]{" + prefix + "})([\\s\\S]+)([\\s\\S]{" + suffix + "})";
        //*的数量是content.length -start-end
        return content.replaceAll(regex, "$1" + replacement + "$3");
    }

    private static String produceCharacter(int len, String character) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < len; i++) {
            sb.append(character);
        }
        return sb.toString();
    }


}

基于接口的注解

基于接口调用待补充


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM