TreeMap 踩坑
2019-11-25 本文已影响0人
得鹿梦为鱼
背景
A系统与第三方系统(C)进行数据对接,需要解决数据防篡改问题,因此一个最为简单的解决方案就是,将要传输的数据以及“一个约定的秘钥信息(key-value)”一起进行加密,并将加密后的值放入签名(signature)一起传给C,C获取到数据后,会对除了signature字段的数据进行加密,最后C将加密结果与A传来的signature值进行对比,如果数据一致,则证明未被篡改
但是在实现时,要保持加密数据的顺序一致,否则,加密结果肯定会不一致
因此采用TreeMap来处理接收到JSON数据【TreeMap具有排序的功能,见结尾】
但是在A、C系统里,对“一个约定的秘钥信息(key-value)” 进行定义时,key一个叫secret(正确的约定名),另一个叫appSecret(错误的约定名),但value是一样的,这导致了TreeMap在排序时,将加密数据(secret的值)错位了,造成接收方解析数据后进行MD5值比对时一直出错
C系统模拟接收A系统数据 C系统校验逻辑这次的教训在于:
1.对TreeMap使用太少,经验不足,未立即反应过来是key的不一致造成的
2.双方约定不够严谨,未精确到防篡改标识的字段名
TreeMap
定义
TreeMap的实现是基于红黑树结构
TreeMap<K,V>的Key值是要求实现java.lang.Comparable,所以迭代的时候TreeMap默认是按照Key值升序排序的,适用于按自然顺序或自定义顺序遍历键(key)
如果K没有实现 Comparable ,则会抛出异常
Exception in thread "main" java.lang.ClassCastException: com.xx.Utils$User cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1294)
at java.util.TreeMap.put(TreeMap.java:538)
使用场景
如果你需要得到一个有序的结果时就应该使用TreeMap(因为HashMap中元素的排列顺序是不固定的,底层实现是基于数组的)