用spring標籤實現欄位的脫敏
阿新 • • 發佈:2019-02-06
問題描述
在springboot中實現資料庫脫敏,可以選擇在物件序列化之前進行處理脫敏,接下來就是具體的操作了。(參考了網上的資料進行了整理)
解決方案
第一步
構建列舉類,用來識別每個脫敏欄位
/**
* @author tori
* 2018/7/16 上午11:19
*/
public enum SensitiveType {
/** 手機號 */
MOBILE,
/** 電子郵箱 */
EMAIL,
/** openId */
OPEN_ID
}
第二步
建立處理脫敏欄位的工具類(這裡只展示了mobile,其他類推)
/**
* @author tori
* 2018/7/16 下午1:57
*/
public class SensitiveUtil {
public static String mobile(String mobile) {
if (StringUtils.isBlank(mobile)) {
return "";
}
return StringUtils.left(mobile, 2).concat(
StringUtils.removeStart(
StringUtils.leftPad(
StringUtils.right(mobile, 4 ), StringUtils.length(mobile), "*"),
"***"));
}
}
第三步
建立標籤類(構建標籤)
/**
* @author tori
* 2018/7/16 上午11:33
*/
//@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveInfoSerialize.class)
public @interface SensitiveInfo {
SensitiveType value();
}
有時在寫標籤類時會碰到@Target,@Retention還有@Order的用法,這裡簡單的概括一下:
@Target
這個註解就是表明該註解類能夠作用的範圍,也就是能夠註解在哪,比如 類、方法、引數等。
下面是他的一些引數:
@Target(ElementType.TYPE) //介面、類、列舉、註解
@Target(ElementType.FIELD) //欄位、列舉的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法引數
@Target(ElementType.CONSTRUCTOR) //建構函式
@Target(ElementType.LOCAL_VARIABLE)//區域性變數
@Target(ElementType.ANNOTATION_TYPE)//註解
@Target(ElementType.PACKAGE) ///包
裡面的引數是可以多選的,使用方法比如@Target({ElementType.METHOD,ElementType.TYPE})。
@Retention
這個註解是保留說明,也就是表明這個註解所註解的類能在哪裡保留,他有三個屬性值:
RetentionPolicy.SOURCE —— 這種型別的Annotations只在原始碼級別保留,編譯時就會被忽略
RetentionPolicy.CLASS —— 這種型別的Annotations編譯時被保留,在class檔案中存在,但JVM將會忽略
RetentionPolicy.RUNTIME —— 這種型別的Annotations將被JVM保留,所以他們能在執行時被JVM或其他使用反射機制的程式碼所讀取和使用。
從上面可以看出一般使用的事第三個屬性,其餘兩個屬性,說實話 我也不清楚什麼情況下使用這兩種。
@Order
@Order標記定義了元件的載入順序,這個標記包含一個value屬性。屬性接受整形值。如:1,2 等等。值越小擁有越高的優先順序。Ordered.HIGHEST_PRECEDENCE這個屬性值是最高優先順序的屬性,它的值是-2147483648,對應的最低屬性值是Ordered.LOWEST_PRECEDENCE,它的值是2147483647。
第四步
最重要的標籤序列化處理類:
/**
* @author tori
* 2018/7/16 下午1:33
*/
public class SensitiveInfoSerialize extends JsonSerializer<String> implements ContextualSerializer {
private SensitiveType type;
public SensitiveInfoSerialize(SensitiveType type) {
this.type = type;
}
public SensitiveInfoSerialize() {}
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
switch (this.type) {
case MOBILE:
gen.writeString(SensitiveUtil.mobile(value));
break;
case EMAIL:
gen.writeString(SensitiveUtil.email(value));
break;
case OPEN_ID:
gen.writeString(SensitiveUtil.openId(value));
break;
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
if (property != null) { // 為空直接跳過
if (Objects.equals(property.getType().getRawClass(), String.class)) { // 非 String 類直接跳過
SensitiveInfo sensitiveInfo = property.getAnnotation(SensitiveInfo.class);
if (sensitiveInfo == null) {
sensitiveInfo = property.getContextAnnotation(SensitiveInfo.class);
}
if (sensitiveInfo != null) { // 如果能得到註解,就將註解的 value 傳入 SensitiveInfoSerialize
return new SensitiveInfoSerialize(sensitiveInfo.value());
}
}
return prov.findValueSerializer(property.getType(), property);
}
return prov.findNullValueSerializer(property);
}
}
最後一步
就是使用和測試啦:
/**
* 手機號碼
*/
@SensitiveInfo(SensitiveType.MOBILE)
private String mobile;
這樣一來獲得的json中mobile,email,openId就可以隱藏部分內容,實現脫敏了。
以上是對spring標籤實現脫敏的流程描述。☺