JSON Java 中的 PII 数据屏蔽
JSON PII data masking in Java
我想屏蔽 JSON 的某些元素并打印到日志中。掩码可以通过替换为虚拟数据或删除密钥对来实现。Java 中是否有实用程序来进行掩码?
例如,
给定 JSON:
{
"key1":"value1",
"key2":"value2",
"key3":"value3",
}
单独屏蔽键 2 并打印 JSON:
{
"key1":"value1",
"key2":"xxxxxx",
"key3":"value3",
}
或
{
"key1":"value1",
"key3":"value3",
}
您可以使用 jackson 将 json 转换为地图、处理地图并将地图转换回 json。
例如:
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
public void mask() throws IOException {
String jsonString = "{\n" +
" \"key1\":\"value1\",\n" +
" \"key2\":\"value2\",\n" +
" \"key3\":\"value3\"\n" +
"}";
Map<String, Object> map;
// Convert json to map
ObjectMapper mapper = new ObjectMapper();
try {
TypeReference ref = new TypeReference<Map<String, Object>>() { };
map = mapper.readValue(jsonString, ref);
} catch (IOException e) {
System.out.print("cannot create Map from json" + e.getMessage());
throw e;
}
// Process map
if(map.containsKey("key2")) {
map.put("key2","xxxxxxxxx");
}
// Convert back map to json
String jsonResult = "";
try {
jsonResult = mapper.writeValueAsString(map);
} catch (IOException e) {
System.out.print("cannot create json from Map" + e.getMessage());
}
System.out.print(jsonResult);
输入将是 JSON 字符串格式的对象或数组类型。这里的可屏蔽键只能是静态的,否则输入字符串将是动态的。
public final class MaskPIData {
/**
* Mask able keywords mentioned here. It should be in LOWER CASE.
*/
private static final Set<String> MASKABLE_KEYS = new HashSet<>(Arrays.asList(
"email",
"emails",
"phone",
"pin",
"password",
"phonenumber",
"moneys"));
private static final String MASKING_VALUE = "****";
private static final ObjectMapper OBJECTMAPPER = new ObjectMapper();
private MaskPIData() {
super();
}
private static boolean isValidSet(Set<String> set) {
return set != null && !set.isEmpty();
}
private static boolean isKnownPrimitiveWrapperModel(Object obj) {
return obj == null || obj instanceof String || obj instanceof Integer || obj instanceof Long
|| obj instanceof Double;
}
@SuppressWarnings("unchecked")
private static JSONObject maskingForJsonObject(Set<String> maskableKeys, JSONObject input) {
if (!isValidSet(maskableKeys) || input == null) {
return input;
}
Map<String, Object> inputMap = (Map<String, Object>) input;
Map<String, Object> caseInsensitiveInputMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
caseInsensitiveInputMap.putAll(inputMap);
for (Map.Entry<String, Object> entryPair : caseInsensitiveInputMap.entrySet()) {
if (entryPair.getValue() instanceof JSONArray) {
JSONArray jsonArr = (JSONArray) caseInsensitiveInputMap.get(entryPair.getKey());
maskingForArray(maskableKeys, entryPair.getKey(), jsonArr);
caseInsensitiveInputMap.put(entryPair.getKey(), jsonArr);
} else if (entryPair.getValue() instanceof JSONObject) {
JSONObject jsonObj = (JSONObject) caseInsensitiveInputMap.get(entryPair.getKey());
caseInsensitiveInputMap.put(entryPair.getKey(), maskingForJsonObject(maskableKeys, jsonObj));
} else if (entryPair.getKey() != null && maskableKeys.contains(entryPair.getKey().toLowerCase())) {
caseInsensitiveInputMap.put(entryPair.getKey(), MASKING_VALUE);
}
}
return OBJECTMAPPER.convertValue(caseInsensitiveInputMap, JSONObject.class);
}
@SuppressWarnings("unchecked")
private static JSONArray maskingForArray(Set<String> maskableKeys, String key,
JSONArray jsonArr) {
JSONArray toRet = jsonArr;
for (int idx = 0; idx < toRet.size(); idx++) {
Object obj = toRet.get(idx);
if (isKnownPrimitiveWrapperModel(obj)) {
if (key != null && maskableKeys.contains(key.toLowerCase())) {
toRet.remove(idx);
toRet.add(idx, MASKING_VALUE);
}
} else {
JSONObject jsonObjFromArray = (JSONObject) toRet.get(idx);
JSONObject maskedJsonObj = maskingForJsonObject(maskableKeys, jsonObjFromArray);
toRet.remove(idx);
toRet.add(idx, maskedJsonObj);
}
}
return toRet;
}
public static String doMask(String input) {
String maskedData = input;
if (maskedData != null && !maskedData.trim().isEmpty()) {
try {
if (new JSONParser().parse(maskedData) instanceof JSONObject) {
JSONObject maskedOutput = maskingForJsonObject(MASKABLE_KEYS,
(JSONObject) new JSONParser().parse(maskedData));
maskedData = OBJECTMAPPER.writeValueAsString(maskedOutput);
} else if (new JSONParser().parse(maskedData) instanceof JSONArray) {
JSONArray maskedOutput = maskingForArray(MASKABLE_KEYS, null, (JSONArray) new JSONParser().parse(maskedData));
maskedData = OBJECTMAPPER.writeValueAsString(maskedOutput);
}
} catch (Exception e) {
// to do - Error while masking data
}
}
return maskedData;
}
public static void main(String args[]) {
String input = "{\"item\":{\"test\":\"test\",\"phone\":\"993244\",\"email\":\"mail@mail.com\"}}";
System.out.println(doMask(input));
}
我想屏蔽 JSON 的某些元素并打印到日志中。掩码可以通过替换为虚拟数据或删除密钥对来实现。Java 中是否有实用程序来进行掩码?
例如,
给定 JSON:
{
"key1":"value1",
"key2":"value2",
"key3":"value3",
}
单独屏蔽键 2 并打印 JSON:
{
"key1":"value1",
"key2":"xxxxxx",
"key3":"value3",
}
或
{
"key1":"value1",
"key3":"value3",
}
您可以使用 jackson 将 json 转换为地图、处理地图并将地图转换回 json。
例如:
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
public void mask() throws IOException {
String jsonString = "{\n" +
" \"key1\":\"value1\",\n" +
" \"key2\":\"value2\",\n" +
" \"key3\":\"value3\"\n" +
"}";
Map<String, Object> map;
// Convert json to map
ObjectMapper mapper = new ObjectMapper();
try {
TypeReference ref = new TypeReference<Map<String, Object>>() { };
map = mapper.readValue(jsonString, ref);
} catch (IOException e) {
System.out.print("cannot create Map from json" + e.getMessage());
throw e;
}
// Process map
if(map.containsKey("key2")) {
map.put("key2","xxxxxxxxx");
}
// Convert back map to json
String jsonResult = "";
try {
jsonResult = mapper.writeValueAsString(map);
} catch (IOException e) {
System.out.print("cannot create json from Map" + e.getMessage());
}
System.out.print(jsonResult);
输入将是 JSON 字符串格式的对象或数组类型。这里的可屏蔽键只能是静态的,否则输入字符串将是动态的。
public final class MaskPIData {
/**
* Mask able keywords mentioned here. It should be in LOWER CASE.
*/
private static final Set<String> MASKABLE_KEYS = new HashSet<>(Arrays.asList(
"email",
"emails",
"phone",
"pin",
"password",
"phonenumber",
"moneys"));
private static final String MASKING_VALUE = "****";
private static final ObjectMapper OBJECTMAPPER = new ObjectMapper();
private MaskPIData() {
super();
}
private static boolean isValidSet(Set<String> set) {
return set != null && !set.isEmpty();
}
private static boolean isKnownPrimitiveWrapperModel(Object obj) {
return obj == null || obj instanceof String || obj instanceof Integer || obj instanceof Long
|| obj instanceof Double;
}
@SuppressWarnings("unchecked")
private static JSONObject maskingForJsonObject(Set<String> maskableKeys, JSONObject input) {
if (!isValidSet(maskableKeys) || input == null) {
return input;
}
Map<String, Object> inputMap = (Map<String, Object>) input;
Map<String, Object> caseInsensitiveInputMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
caseInsensitiveInputMap.putAll(inputMap);
for (Map.Entry<String, Object> entryPair : caseInsensitiveInputMap.entrySet()) {
if (entryPair.getValue() instanceof JSONArray) {
JSONArray jsonArr = (JSONArray) caseInsensitiveInputMap.get(entryPair.getKey());
maskingForArray(maskableKeys, entryPair.getKey(), jsonArr);
caseInsensitiveInputMap.put(entryPair.getKey(), jsonArr);
} else if (entryPair.getValue() instanceof JSONObject) {
JSONObject jsonObj = (JSONObject) caseInsensitiveInputMap.get(entryPair.getKey());
caseInsensitiveInputMap.put(entryPair.getKey(), maskingForJsonObject(maskableKeys, jsonObj));
} else if (entryPair.getKey() != null && maskableKeys.contains(entryPair.getKey().toLowerCase())) {
caseInsensitiveInputMap.put(entryPair.getKey(), MASKING_VALUE);
}
}
return OBJECTMAPPER.convertValue(caseInsensitiveInputMap, JSONObject.class);
}
@SuppressWarnings("unchecked")
private static JSONArray maskingForArray(Set<String> maskableKeys, String key,
JSONArray jsonArr) {
JSONArray toRet = jsonArr;
for (int idx = 0; idx < toRet.size(); idx++) {
Object obj = toRet.get(idx);
if (isKnownPrimitiveWrapperModel(obj)) {
if (key != null && maskableKeys.contains(key.toLowerCase())) {
toRet.remove(idx);
toRet.add(idx, MASKING_VALUE);
}
} else {
JSONObject jsonObjFromArray = (JSONObject) toRet.get(idx);
JSONObject maskedJsonObj = maskingForJsonObject(maskableKeys, jsonObjFromArray);
toRet.remove(idx);
toRet.add(idx, maskedJsonObj);
}
}
return toRet;
}
public static String doMask(String input) {
String maskedData = input;
if (maskedData != null && !maskedData.trim().isEmpty()) {
try {
if (new JSONParser().parse(maskedData) instanceof JSONObject) {
JSONObject maskedOutput = maskingForJsonObject(MASKABLE_KEYS,
(JSONObject) new JSONParser().parse(maskedData));
maskedData = OBJECTMAPPER.writeValueAsString(maskedOutput);
} else if (new JSONParser().parse(maskedData) instanceof JSONArray) {
JSONArray maskedOutput = maskingForArray(MASKABLE_KEYS, null, (JSONArray) new JSONParser().parse(maskedData));
maskedData = OBJECTMAPPER.writeValueAsString(maskedOutput);
}
} catch (Exception e) {
// to do - Error while masking data
}
}
return maskedData;
}
public static void main(String args[]) {
String input = "{\"item\":{\"test\":\"test\",\"phone\":\"993244\",\"email\":\"mail@mail.com\"}}";
System.out.println(doMask(input));
}