Java代码混淆和JSON数据序列化问题
基本观点:
第一点:Java代码生成的Jar文件很容易被反编译,常用工具JD-GUI(http://jd.benow.ca/)
第二点:Jar文件常用的“加密”方式是混淆(有专门的混淆软件,有些需要收费的),使得类名、类中字段和方法名称等难以肉眼判断。例如
第三点:JSON协议使用方便,非常流行。常用框架由于可以使用自定义Model类,直接转换成JSON格式的数据,使用起来方便快捷。我使用的alibaba的fastjson.jar。(吐槽一下:虽然该包有不少bug需要进一步完善,整体已经相当不错了。) 例如:
基本的Model
public class User { private String name; private int age; public User() { } public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
测试:
import com.alibaba.fastjson.JSONObject; public class Test { public static void main(String[] args) { String json = JSONObject.toJSONString(new User("wsc", 25)); System.out.println(json); User user = JSONObject.parseObject(json, User.class); System.out.println(user.getAge()); System.out.println(user.getName()); } }
打印:
{"age":25,"name":"wsc"} 25 wsc
第四点:
当使用框架转换Model为String类型的JSON数据时,通常是根据Model的set和get方法获取需要保存到磁盘的字段名称,常见手段是反射,如果直接获取Field,可能会产生很多,包括某些Field其实用户不想保存到磁盘transient字段或者中间变量字段,尽管fastjson.jar使用了字节码框架ASM来提高效率,也是需要通过set/get方法获取到字段名称。
问题:
如果使用了混淆,代码中字段和方法名称都被混淆,JavaBean的规则被改写,确实是能反序列化出对象,但是可能User名称已经被更改为AA,属性Name可能被更改为f.这个时候就会出现异常。
解决办法:
方法1:有些人推荐set和get方法不适用混淆,相当于Model的结构是公开的,虽然能够避免,总体不安全。
方法2:JSON序列化还有另外一种机制,Model是Map类型
Map是直接获取字段名称的。
使用方法2的缺点是:当你反序列化的时候,如果你的Model里字段类型是自定义类对象,比如User对象中Age不是String,而是自定义类型Age,它是无法帮你自动反序列化成自定义对象Age的,需要手动创建。
举例:
AppCheckBasic是一个基本Model,集成了JSONObject,由于JOSNObject本身是Map结构,所以AppCheckBasic也是一个Map。
AppCheckBasic有一个属性apps,它是List<AppBasic> 类型。
public class AppCheckBasic extends JSONObject { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") public void initial() { // 把所有层次结构初始化 List<AppBasic> apps = null; Object obj = this.get("apps"); // 初始化赋值后使用 if (obj instanceof ArrayList) { apps = (List<AppBasic>) obj; } // 反序列化(非第一次初始化后) if (obj instanceof JSONArray) { JSONArray array = (JSONArray) this.get("apps"); apps = new ArrayList<AppBasic>(); for (int i = 0; i < array.size(); i++) { // AppBasic内部没有"复杂"数据类型 AppBasic appBasic = JSON.parseObject(array.getString(i), AppBasic.class); apps.add(appBasic); } } // 初始化内容 this.put("apps", apps); } // set和get方法是为了方便 @SuppressWarnings("unchecked") public List<AppBasic> getApps() { List<AppBasic> apps = (List<AppBasic>) this.get("apps"); return apps; } public void setApps(List<AppBasic> apps) { this.put("apps", apps); } }
除了必须手动反序列化重建自定义对象或者复杂对象如List等,为了方便为该Map类型的Bean定义set和get方法。
相关推荐
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用grizzly作为通信框架,采用pb作为序列化/反序列化时,tps为168k次/秒。 其支持的功能主要为: 1、透明的调用远端服务器提供的功能...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...