最近同事发现有接口签名验证通不过,查了许久,发现,两边的验签规则不一样。最大的差异在于时间戳是否参与参数的排序。使用较多的版本是时间戳参与参数排序,而突然出一个接口中的时间戳不参与排序,导致算出来的签名值不一样。让我们使用一段main方法来感受一下其中的差异。
public static void main(String[] args) {
System.out.println(“SortedMap”);
SortedMap<String, String> sortedDict = new TreeMap<>(Collator.getInstance());
sortedDict.put(“B”, “B”);
sortedDict.put(“A”, “A”);
sortedDict.put(“C”, “C”);
System.out.println(sortedDict);
System.out.println(“LinkedHashMap”);
Map<String, String> dic = new LinkedHashMap<>();
dic.put(“B”, “B”);
dic.put(“A”, “A”);
dic.put(“C”, “C”);
System.out.println(dic);
System.out.println(“HashMap”);
Map<String, String> hashMapDic = new HashMap<>();
hashMapDic.put(“B”, “B”);
hashMapDic.put(“A”, “A”);
hashMapDic.put(“C”, “C”);
System.out.println(hashMapDic);
}
输出的结果:
SortedMap
{A=A, B=B, C=C}
LinkedHashMap
{B=B, A=A, C=C}
HashMap
{A=A, B=B, C=C}
很显示,当我们使用SortedMap、HashMap来处理签名参数的时候,参数自动排序了,而当我们使用LinkedHashMap处理的时候参数则不会排序。
造成问题产生的原因,看起来是使用了LinkedHashMap导致的,仔细分析,完全是两种签名处理思路导致的。
推荐思路一:使用SortedMap、HashMap做预处理,与顺序无关
不推荐思路二,没有对url中的query参数做任何预处理,直接在尾部附加上了时间戳,省了一步参数预处理。
思路二的问题在于,参数的顺序会影响最终签名,调用方需要知晓参数顺序。如果大家都知道并严格执行签名顺序,思路二其实也是正常的可行的。但是一般来讲,团队成员可能不断变化,一不留神就掉进这个洞里了。推荐使用思路一进行签名验证。
思路一与思路二的验证方式如何对接上呢?
在思路一追加时间戳之前,需要创建一个LinkedHashMap,将处理过的参数put进去,再将时间戳put进去,之后生成的签名URL就与思路二是一致的。
小结:当我们设计接口签名规则时,可以遵循一下一个重要的规则,参数顺序无关。
签名参考流程:
1.参数提取,记得使用SortedMap或HashMap
2.过滤处理
3.生成待签名URL
4.签名
5.生成签名后的URL