java 序列化 混淆_代码混淆与JSON数据序列化问题

本文探讨了Java代码混淆对JSON数据序列化的影响。混淆可能导致JavaBean的字段和方法名称改变,引起反序列化异常。解决方案包括保留set/get方法不混淆或使用Map类型的Model,但后者在处理自定义对象时需要手动反序列化。
摘要由CSDN通过智能技术生成

Java代码混淆和JSON数据序列化问题

基本观点:

第一点:Java代码生成的Jar文件很容易被反编译,常用工具JD-GUI(http://jd.benow.ca/)

第二点:Jar文件常用的“加密”方式是混淆(有专门的混淆软件,有些需要收费的),使得类名、类中字段和方法名称等难以肉眼判断。例如

3b880da18165b5b5d688e748d12d5ef9.png

第三点: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类型

9dc107a30d6353cf1011bb1e706458b3.png

Map是直接获取字段名称的。

使用方法2的缺点是:当你反序列化的时候,如果你的Model里字段类型是自定义类对象,比如User对象中Age不是String,而是自定义类型Age,它是无法帮你自动反序列化成自定义对象Age的,需要手动创建。

举例:

AppCheckBasic是一个基本Model,集成了JSONObject,由于JOSNObject本身是Map结构,所以AppCheckBasic也是一个Map。

AppCheckBasic有一个属性apps,它是List 类型。

public class AppCheckBasic extends JSONObject {

private static final long serialVersionUID = 1L;

@SuppressWarnings("unchecked")

public void initial() {

// 把所有层次结构初始化

List apps = null;

Object obj = this.get("apps");

// 初始化赋值后使用

if (obj instanceof ArrayList) {

apps = (List) obj;

}

// 反序列化(非第一次初始化后)

if (obj instanceof JSONArray) {

JSONArray array = (JSONArray) this.get("apps");

apps = new ArrayList();

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 getApps() {

List apps = (List) this.get("apps");

return apps;

}

public void setApps(List apps) {

this.put("apps", apps);

}

}

除了必须手动反序列化重建自定义对象或者复杂对象如List等,为了方便为该Map类型的Bean定义set和get方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值