签名校验相信不少小伙伴都有碰到过,微信jsapi集成、支付宝集成的时候都会需要加上签名。
这边记录一下当待签名内容是json字符串时的排序方法。
后端(java):
方法一:利用TreeMap
TreeMap本身就是有序集合,每一次插入删除都会进行排序。
Map<String, String> map = new TreeMap<String, String>();
JSONObject jp = new JSONObject();
for (Iterator<String> it = map.keySet().iterator(); it.hasNext();) {
if (!"sign".equals(key)) {
jp.put(key, map.get(key));
}
}
方法二:利用List
Map<String, String> map = new HashMap<String, String>();
List<Map.Entry<String, String>> list=new ArrayList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Entry<String, String> o1,Entry<String, String> o2) {
return o1.getKey().compareTo(o2.getKey());//这里如果是getValue的话就是根据value排序
}
});
接下来遍历list,往JSONObject中put值就行了。
for (Entry<String, String> entry : list) {
if (!"sign".equals(key)) {
jp.put(entry.getKey(), entry.getValue());
}
}
方法三:
利用Arrays.sort
Object[] key_arr = params.keySet().toArray();
Arrays.sort(key_arr);
for (Object key : key_arr) {
if (!"sign".equals(key)) {
jp.put(key, params.get(key));
}
}
注:以上import net.sf.json.JSONObject;
前端:
原生js中好像没有对JSON对象按键值排序的方法(反正我没找到- -),那么就只好自己手动拼装了。
当请求参数对象param都是string键值对时,可以用以下方法生成排好序的JSON字符串:
var generateJson=function (param) {
var keys=Object.keys(param).sort();
var json="{";
angular.forEach(keys,function (data) {
json+='"'+data+'":"'+param[data]+'",';
});
json=json.substr(0,json.length-1);
json+="}";
return json;
}
当param中存在某个key对应的value是对象而非字符串时,就要特殊处理一下了:
假设
var param={
appVersion:‘1.0.0’,
sysVersion:‘1.0.1’,
deviceType:‘0’,
deviceModel:‘Nokia’,
fields:{
a:'1',
b:'2'
}
};
如果还用generateJson()方法,那么param[data]取到的将是[Object,Object],所以在拼装json字符串的时候,要将fileds先转换为字符串,即将fileds的值看做一个字符串。
if(data=='fileds'){
json+='"'+data+'":"'+JSON.stringify(param.fields)+',';
}