1. 程式人生 > 其它 >註解進行資料脫敏處理

註解進行資料脫敏處理

1.定義註解和列舉類

package com.joolun.common.sensitive;

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /** * 脫敏註解 * * @author JooLun * @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html **/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @JacksonAnnotationsInside @JsonSerialize(using = SensitiveSerialize.class) public @interface Sensitive {
/** * 脫敏資料型別 */ SensitiveTypeEnum type(); }
package com.joolun.common.sensitive;

/**
 * 敏感資訊列舉類
 *
 * @author JooLun
 * @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
 **/
public enum SensitiveTypeEnum {

    /**
     * 使用者名稱, 李*天, 張*
     */
    CHINESE_NAME,
    /**
     * 手機號, 185****1653
     
*/ MOBILE_PHONE, /** * 電子郵件, r*****[email protected] */ EMAIL, /** * 密碼, ****** */ PASSWORD, /** * 金鑰, 最後三位其他都是*** */ KEY }

2.脫敏工具類和業務類

package com.joolun.common.sensitive;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.joolun.common.utils.SensitiveUtils;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Objects;

/**
 * @author JooLun
 * @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
 * 脫敏序列化
 */
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {

    private SensitiveTypeEnum type;

    @Override
    public void serialize(final String originStr, final JsonGenerator jsonGenerator,
                          final SerializerProvider serializerProvider) throws IOException {
        switch (type) {
        case CHINESE_NAME:
            jsonGenerator.writeString(SensitiveUtils.chineseName(originStr));
            break;
        case MOBILE_PHONE:
            jsonGenerator.writeString(SensitiveUtils.mobilePhone(originStr));
            break;
        case EMAIL:
            jsonGenerator.writeString(SensitiveUtils.email(originStr));
            break;
        case PASSWORD:
            jsonGenerator.writeString(SensitiveUtils.password(originStr));
            break;
        case KEY:
            jsonGenerator.writeString(SensitiveUtils.key(originStr));
            break;
        default:
            throw new IllegalArgumentException("未定義的敏感資訊列舉類" + type);
        }
    }

    @Override
    public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider, final BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) {
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
                if (sensitive == null) {
                    sensitive = beanProperty.getContextAnnotation(Sensitive.class);
                }
                if (sensitive != null) {
                    return new SensitiveSerialize(sensitive.type());
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }

}
package com.joolun.common.utils;

import cn.hutool.core.util.StrUtil;

/**
 * 資料脫敏工具類
 *
 * @Author: JooLun
 * @Author: https://www.cnblogs.com/xiluonanfeng/p/10183926.html
 * @Date: 2021/7/19 16:21
 */
public class SensitiveUtils {

    /**
     * 預設填充字元
     */
    public static final String DEFAULT_PAD_STR = "*";

    /**
     * 資料脫敏
     *
     */
    public static String process(String data) {
        return process(data, 2, 1, DEFAULT_PAD_STR);
    }

    /**
     * 資料脫敏
     *
     */
    public static String process(String data, Integer leftLen, Integer rightLen) {
        return process(data, leftLen, rightLen, DEFAULT_PAD_STR);
    }

    /**
     * 對字串進行脫敏操作
     * @param originStr 原始字串
     * @param prefixNoMaskLen 左側需要保留幾位明文欄位
     * @param suffixNoMaskLen 右側需要保留幾位明文欄位
     * @param maskStr 用於遮罩的字串, 如'*'
     * @return 脫敏後結果
     */
    public static String process(String originStr, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) {
        if (originStr == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0, n = originStr.length(); i < n; i++) {
            if (i < prefixNoMaskLen) {
                sb.append(originStr.charAt(i));
                continue;
            }
            if (i > (n - suffixNoMaskLen - 1)) {
                sb.append(originStr.charAt(i));
                continue;
            }
            sb.append(maskStr);
        }
        return sb.toString();
    }

    /**
     * 中文姓名只顯示最後一個漢字
     * @param fullName 姓名
     * @return
     */
    public static String chineseName(String fullName) {
        if (fullName == null) {
            return null;
        }
        return process(fullName, 0, 1, DEFAULT_PAD_STR);
    }

    /**
     * 手機號碼前三位,後四位,如186****2356
     * @param num 手機號碼
     * @return
     */
    public static String mobilePhone(String num) {
        return process(num, 0, 4, DEFAULT_PAD_STR);
    }

    /**
     * 地址只顯示到地區
     * @param address 地址
     * @return
     */
    public static String address(String address) {
        return process(address, 6, 0, DEFAULT_PAD_STR);
    }

    /**
     * 電子郵箱 僅顯示第一個字母,@後面的地址顯示,比如:r**@qq.com
     * @param email 電子郵箱
     * @return
     */
    public static String email(String email) {
        if (email == null) {
            return null;
        }
        int index = StrUtil.indexOf(email, '@');
        if (index <= 1) {
            return email;
        }
        String preEmail = process(email.substring(0, index), 1, 0, DEFAULT_PAD_STR);
        return preEmail + email.substring(index);

    }

    /**
     * 密碼的全部字元,如:******
     * @param password 密碼
     * @return
     */
    public static String password(String password) {
        if (password == null) {
            return null;
        }
        return "******";
    }

    /**
     * 金鑰除了最後三位,全部,比如:***klo
     * @param key 金鑰
     * @return 結果
     */
    public static String key(String key) {
        if (key == null) {
            return null;
        }
        int viewLength = 6;
        StringBuilder tmpKey = new StringBuilder(process(key, 0, 3, DEFAULT_PAD_STR));
        if (tmpKey.length() > viewLength) {
            return tmpKey.substring(tmpKey.length() - viewLength);
        }
        else if (tmpKey.length() < viewLength) {
            int buffLength = viewLength - tmpKey.length();
            for (int i = 0; i < buffLength; i++) {
                tmpKey.insert(0, DEFAULT_PAD_STR);
            }
            return tmpKey.toString();
        }
        else {
            return tmpKey.toString();
        }
    }

    public static void main(String[] args) {
        String s = mobilePhone("18653653621");
        System.out.println(s);
    }
}

3.實體類使用

  /**
   * 電話號碼
   */
    @ApiModelProperty(value = "電話號碼")
    @Sensitive(type = SensitiveTypeEnum.MOBILE_PHONE)
    private String telNum;