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中批量指定属性和税敏方式, 一次性转换, 性能较高, 但是只能对同一节点下的一批属性值脱敏

 

posted @ 2022-08-17 14:06  苦涩泪滴  阅读(516)  评论(0编辑  收藏  举报