如何修改JSON字符串中的敏感信息

 更新时间:2021年12月18日 11:15:58   作者:yuan487639  
这篇文章主要介绍了如何修改JSON字符串中的敏感信息,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

修改JSON字符串中的敏感信息

项目要求把json字符串里面的敏感信息加密

比如手机号身份证之类,这就要求遍历json,并且覆盖所有的敏感key,原本以为挺难的,静下心来想了想,代码修修改改大约一个小时搞定了,其实是一个简单的递归,跟遍历一个目录并输出所有文件名一样

废话少说,直接贴代码和测试用例。

package com.ucredit.test; 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
 
/**
 * Created by beibei on 18/1/24.
 */
public class JsonTest { 
    public static void main(String[] args) {
        String sa = "{'sa':'saas','sb':['sa','ds','sda'],'sc':{'dsa':'21'}}";
        JSONObject jsonObject = JSON.parseObject(sa);
        System.out.println(changeSensitiveMsg(jsonObject).toJSONString());
    }
 
    //递归对象
    private static JSONObject changeSensitiveMsg(JSONObject jsonObject) {
        for (String key : jsonObject.keySet()) {
            String json = jsonObject.getString(key);
            if (isObject(json)) {
                jsonObject.put(key, changeSensitiveMsg(JSON.parseObject(json)));
            } else if (isArray(json)) {
                jsonObject.put(key, changeSensitiveMsg(JSON.parseArray(json)));
            } else {
                //这里才是最终覆盖敏感属性的操作
                if (isSensitiveKey(key))
                    jsonObject.put(key, "测试");
            }
        }
        return jsonObject;
    }
 
    //递归数组
    private static JSONArray changeSensitiveMsg(JSONArray jsonArray) {
        for (int i = 0; i < jsonArray.size(); i++) {
            String value = jsonArray.getString(i);
            if (isArray(value)) {
                jsonArray.set(i, changeSensitiveMsg(jsonArray.getJSONArray(i)));
            } else if (isObject(value)) {
                jsonArray.set(i, changeSensitiveMsg(JSON.parseObject(value)));
            }
        }
        return jsonArray;
    }
 
    //判断是否是对象,这个方法需要优化,遇到特殊字符相当占时间,可以根据json串首字母直接判断
    private static boolean isObject(String str) {
        try {
            JSON.parseObject(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
 
    //判断是否是数组,这个方法需要优化,遇到特殊字符相当占时间,可以根据json串首字母直接判断
    private static boolean isArray(String str) {
        try {
            JSON.parseArray(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
 
    //是否是敏感key
    public static boolean isSensitiveKey(String key) {
        return true;
    }
}

清除敏感字符串内容

连接邮箱、短信等服务器信息中密码属于敏感信息,需要在内存中清除。常规做法是前台传递密码明文对应char[],使用完后把数组每个元素修改为0。

但是必须出现String的情况不适用,比如:连接邮箱服务器使用的用户密码;调用rest接口传递的json字符串包含密码明文。

分析

字符串为final类型,运行期间不可改变,涉及常量池,赋值为null并不会回收内存。但是new String不同,可以回收内存。但是JVM回收不及时,要是可以在使用完成后清除char[]内容,也可以做到不改变常量池中的内容。问题转化为如何清理new String内存?

解决思路

String只是一个引用,它的内容是char[] value,value为内部私有变量,不可以访问。

但是java反射可以搞定这件事,代码如下:

char[] chars = new char[] { 'a', 'a', 'a', 'a' };
String valueStr = new String(chars);
System.out.println(valueStr);
Field field = valueStr.getClass().getDeclaredField("value");
field.setAccessible(true);
field.set(valueStr, new char[] { 0, 0, 0, 0 });
field.setAccessible(false);
System.out.println(valueStr);
System.out.println("aaaa");
System.out.println(new String(new char[] { 'a', 'a', 'a', 'a' }));

改变了私有变量为可访问权限,得到value,改变数组的值,然后再把权限设回去。加上打印常量池字符串和new String同样的内容

测试证明,这种方法是可行的,不会改变后面同样内容的字符串内容。通过查看源码,org.codehaus.jackson.map.ObjectMapper.writeValueAsString(Object value) 方法,返回的字符串也是new String,所以也是适用的。经过测试,不会影响其它相同内容的json字符串。

这样,对于json字符串和new String都可以使用这样的方式清除敏感信息内容。但是需要注意的是:如果不是new出来的字符串,一旦修改了,就会影响常量池字符串内容,后果很严重。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java中如何正确定义字符串

    Java中如何正确定义字符串

    这篇文章主要给大家介绍了关于Java中如何正确定义字符串的相关资料,在Java中定义一个字符串最简单的方法是用双引号把它包围起来,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • RestTemplate发送请求时Cookie的影响及注意事项说明

    RestTemplate发送请求时Cookie的影响及注意事项说明

    这篇文章主要介绍了RestTemplate发送请求时Cookie的影响及注意事项说明,具有很好的参考价值,希望对大家有所帮助。
    2023-07-07
  • 详解如何通过Java实现类似Nginx代理

    详解如何通过Java实现类似Nginx代理

    最近遇到一个问题,在内网环境中部署的项目需要调用外网完成一些应用,一般情况我们可以通过增加一台机器,部署到可以访问外网的服务器上,然后内网直接连接该机器通过Nginx进行代理即可,所以本文介绍了如何通过Java实现类似Nginx代理,需要的朋友可以参考下
    2024-08-08
  • BeanUtils.copyProperties复制属性失败的原因及解决方案

    BeanUtils.copyProperties复制属性失败的原因及解决方案

    这篇文章主要介绍了BeanUtils.copyProperties复制属性失败的原因及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 解决在Idea 2020.2下使用 Lombok的注解不生效的问题(插件安装了,依赖也写了,自动注解也设置了)

    解决在Idea 2020.2下使用 Lombok的注解不生效的问题(插件安装了,依赖也写了,自动注解也设置了)

    这篇文章主要介绍了在Idea 2020.2下使用 Lombok的注解不生效的问题(插件安装了,依赖也写了,自动注解也设置了),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • springboot实现返回视图而不是string的方法

    springboot实现返回视图而不是string的方法

    这篇文章主要介绍了springboot实现返回视图而不是string的方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • JAVA线程池原理实例详解

    JAVA线程池原理实例详解

    这篇文章主要介绍了JAVA线程池原理,结合实例形式详细分析了java线程池概念、原理、创建、使用方法及相关注意事项,需要的朋友可以参考下
    2019-03-03
  • Java设计模式之外观模式的实现方式

    Java设计模式之外观模式的实现方式

    这篇文章主要介绍了Java设计模式之外观模式的实现方式,外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口,这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性,需要的朋友可以参考下
    2023-11-11
  • Vue结合Springboot实现用户列表单页面(前后端分离)

    Vue结合Springboot实现用户列表单页面(前后端分离)

    本文主要介绍了Vue结合Springboot实现用户列表单页面,可以实现简单的查询,删除,修改,和添加用户信息功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • MyBatis与MyBatis-Plus的区别详解

    MyBatis与MyBatis-Plus的区别详解

    本文主要介绍了MyBatis与MyBatis-Plus的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05

最新评论