1. 程式人生 > 實用技巧 >記一次mybatis攔截器實現資料脫敏

記一次mybatis攔截器實現資料脫敏

1. 首先定義一個註解,用來標註哪些欄位需要脫敏

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface DataHide {
}

2. 定義一個數據實體DO

@TableName("person")
@Data
public class PersonDO {
    @TableId
    private Integer id;
    private String firstName;
    @DataHide  // 要做脫敏的欄位
    private String lastName;
}

3. 寫一個外掛(攔截器)

/**
 * @author yangxj
 * @date 2020-08-10 11:31
 * <p>
 * 資料脫敏攔截器
 */
@Component
@Intercepts(@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = Statement.class))
public class DataHidePlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws
Throwable { List result = (List) invocation.proceed(); return dataHide(result); }
@SuppressWarnings(
"unchecked") private List dataHide(List result) { if (result.isEmpty()) return result; Class<?> clazz = result.get(0).getClass(); // 基本型別或者基本型別的包裝型別跳過
if (isWrapClass(clazz)) return result; // 獲取欄位開始處理 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { // 包含脫敏註解欄位做脫敏處理 if (field.isAnnotationPresent(DataHide.class)) { result.forEach(originData -> doHide(originData, field)); } } return result; } private boolean isWrapClass(Class<?> clazz) { try { return clazz.isPrimitive() || ((Class) clazz.getField("TYPE").get(null)).isPrimitive(); } catch (Exception e) { return false; } } private void doHide(Object originData, Field field) { try { field.setAccessible(true);
//TODO 具體脫敏規則自行實現... field.set(originData,
"**" + field.get(originData) + "**"); } catch (Exception e) { } } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } }

5. over