fastjson處理脫敏中的指定字段值[原]

 

需求

假如D://txt/json.json文件內容如下 , 現期望students列表中的studentName和studentMobile脫敏後返回給前端

{
  "teacher": {
    "id": "t0001",
    "name": "王老師",
    "age": 24
  },
  "students": [
    {
      "id": "s0001",
      "createDate": "2022-08-16 16:37:21",
      "updateDate": "2022-08-16 16:37:21",
      "studentName": "胡歌",
      "studentMobile": "13712345678"
    },
    {
      "id": "s0002",
      "createDate": "2022-08-17 16:37:21",
      "updateDate": "2022-08-17 16:37:21",
      "studentName": "張天愛",
      "studentMobile": "13787654321"
    }
  ]
}

 

依賴

本方法依賴包 , 

hutool-all.jar

fastjson

 

原理

使用fastjson的JSONPath提取對應路徑下的節點 , 再使用hutool對指定的節點實現脫敏 , 當然hutool在本處並不是絕對必須的 , 脫敏方法可以自己手動修改成不依賴hutool 的 StrUtil.hide(value, startIndex, endIndex); 方法

 

工具類代碼

package com.rosellete.iescp.cshop.tool;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 字符串隱藏工具
 * fastjson處理脫敏中的指定字段值[原]==>https://www.cnblogs.com/whatlonelytear/p/16594961.html
 * @author 金劍波
 * @date 2022/08/17
 */
public class HideTool {

    public static String IDCARD = "idcard";//身份證
    public static String MOBILE = "mobile";//手機
    public static String NAME = "name";//姓名

    public static void main(String[] args) {
        String data = FileUtil.readString("D://txt/json.json", Charset.forName("utf-8"));

                //使用方式1,直接指定屬性和脫敏方式,串行轉換,性能較低
        Object srcObj1 = JSONObject.parse(data);

        srcObj1 = HideTool.doHide(srcObj1, "$.students", "studentMobile", HideTool.MOBILE);
        srcObj1 = HideTool.doHide(srcObj1, "$.students", "studentName", HideTool.NAME);
        System.out.println("方式1脫敏後效果↓");
        System.out.println(JSON.toJSONString(srcObj1));

        //使用方式2,在map中批量指定屬性和稅敏方式,一次性轉換,性能較高
        Object srcObj2 = JSONObject.parse(data);
        Map map = new HashMap<String, String>();
        map.put("studentMobile", HideTool.MOBILE);
        map.put("studentName", HideTool.NAME);
        Object hideResult2 = HideTool.doHide(srcObj2, "$.students", map);
        System.out.println("方式2脫敏後效果↓");
        System.out.println(JSON.toJSONString(hideResult2));


    }

    /**
     * 脫敏目標對象是指定路徑的某一個鍵值
     *
     * @param srcObject 原始對象
     * @param path      jsonPath路徑
     * @param key       屬性名, 鍵名
     * @param type      隱藏類型
     * @return
     */
    public static Object doHide(Object srcObject, String path, String key, String type) {
        Map map = new HashMap<String, String>();
        map.put(key, type);
        return doHide(srcObject, path, map);
    }

    /**
     * 脫敏目標對象是指定路徑的某一批鍵值
     *
     * @param srcObject 原始對象
     * @param path      jsonPath路徑
     * @param kv        map.put("mobile", HideTool.MOBILE);map.put("name", HideTool.NAME);
     * @return
     */
    public static Object doHide(Object srcObject, String path, Map<String, String> kv) {
        JSONObject targetObj;//目標對象
        if (srcObject instanceof JSONObject) {
            targetObj = (JSONObject) srcObject;
        } else {
            final String jsonString = JSON.toJSONString(srcObject);
            targetObj = JSON.parseObject(jsonString);
        }
        final int dataSize = JSONPath.size(targetObj, path);
        if (dataSize >= 1) {
            Object dataObj = JSONPath.eval(targetObj, path);
            if (dataObj instanceof List) {
                for (Object obj : (List) dataObj) {
                    JSONObject o1 = (JSONObject) obj;
                    for (Map.Entry<String, String> entry : kv.entrySet()) {
                        String value1 = o1.getOrDefault(entry.getKey(), "").toString();
                        value1 = hideDetail(value1, entry.getValue());
                        o1.put(entry.getKey(), value1);
                    }

                }
            } else {
                JSONObject o1 = (JSONObject) dataObj;
                for (Map.Entry<String, String> entry : kv.entrySet()) {
                    String value1 = o1.getOrDefault(entry.getKey(), "").toString();
                    value1 = hideDetail(value1, entry.getValue());
                    o1.put(entry.getKey(), value1);
                }
            }
            //System.out.println(JSON.toJSONString(dataObj));
        }
        return targetObj;
    }

    /**
     * 脫敏詳情
     *
     * @param value 原值
     * @param type  脫敏類型
     * @return
     */
    private static String hideDetail(String value, String type) {
        switch (type) {
            case "idcard":
                value = StrUtil.hide(value, 5, 16);
                break;
            case "mobile":
                value = StrUtil.hide(value, 3, 7);
                break;
            case "name":
                if (value.length() <= 2) {
                    value = StrUtil.hide(value, 1, value.length());
                } else {
                    value = StrUtil.hide(value, 1, value.length() - 1);
                }
                break;
            default:
                throw new RuntimeException("非法脫敏類型");
        }
        return value;
    }

}

 

執行結果

方式1脫敏後效果↓
{"teacher":{"name":"王老師","id":"t0001","age":24},"students":[{"updateDate":"2022-08-16 16:37:21","studentName":"胡*","studentMobile":"137****5678","id":"s0001","createDate":"2022-08-16 16:37:21"},{"updateDate":"2022-08-17 16:37:21","studentName":"張*愛","studentMobile":"137****4321","id":"s0002","createDate":"2022-08-17 16:37:21"}]}
方式2脫敏後效果↓
{"teacher":{"name":"王老師","id":"t0001","age":24},"students":[{"updateDate":"2022-08-16 16:37:21","studentName":"胡*","studentMobile":"137****5678","id":"s0001","createDate":"2022-08-16 16:37:21"},{"updateDate":"2022-08-17 16:37:21","studentName":"張*愛","studentMobile":"137****4321","id":"s0002","createDate":"2022-08-17 16:37:21"}]}

 

最終studentName和studentMobile都按各自方式實現了脫敏處理. 

 

 

優缺點

該工具類實現對象的脫敏非常方便 , 

使用方式1, 直接指定屬性和脫敏方式, 串行轉換, 性能較低, 但是可以對不同節點下的屬性值一點點脫敏

使用方式2, 在map中批量指定屬性和稅敏方式, 一次性轉換, 性能較高, 但是隻能對同一節點下的一批屬性值脫敏

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章