go map 按字典升序排序后转 JSON md5 与 PHP 不一致
資深大佬 : Nick66 10
源码如下
package main import ( "fmt" "sort" "encoding/json" "crypto/md5" "encoding/hex" "bytes" ) func main() { params := make(map[string]string) params["name"] = "111" params["domain"] = "www.baidu.com?name=1&id=1" // 排序 keys := make([]string, len(params)) i := 0 for k, _ := range params { keys[i] = k i++ } sort.Strings(keys) for _, k := range keys { fmt.Println(k) } byteBuf := bytes.NewBuffer([]byte{}) encoder := json.NewEncoder(byteBuf) // 特殊字符不转义 encoder.SetEscapeHTML(false) err := encoder.Encode(params) if err != nil { panic(err) } data := byteBuf.String() fmt.Println(data) h := md5.New() // 与 php 一致 h.Write([]byte(`{"domain":"www.baidu.com?name=1&id=1","name":"111"}`)) // 不一致 // h.Write([]byte(data)) fmt.Println(hex.EncodeToString(h.Sum(nil))) // php 结果为 06820973e7b8d3acdb4763264a803620 }
大佬有話說 (12)
-
資深大佬 : also24说个题外话:
也不知道谁带起的这种风气,用这种方式来进行检验。JSON 序列化的时候,是否换行,是否缩进,是否转义都会造成序列化结果字符串的差异。
正确的做法是直接传输序列化后的 JSON String,计算 hash 的时候也直接针对整个 JSON String
-
主 資深大佬 : Nick66@also24 确实是这样,现在这个功能就为了把参数 md5 之后作为签名参数用
-
資深大佬 : marquinajson 在我这个 pythoner 眼里就是一个 dict,我也从来不会对 json 序列化、反序列化时 key 的顺序有任何期待,更别提算 md5 这种操作了
-
主 資深大佬 : Nick66@marquina 接手项目的时候就是这样,我也无法改变,只能想办法解决。
-
資深大佬 : haiyang416@Nick66 https://github.com/golang/go/commit/6f25f1d4c901417af1da65e41992d71c30f64f8f
strings.Trim 一下。
-
資深大佬 : chinvo签名的正确玩法是对 http body 签名,签名结果放到 header 里
这样就不涉及排序问题
-
主 資深大佬 : Nick66@haiyang416 感谢,解决了。
-
資深大佬 : VegetablebyteBuf.Bytes()
[123 34 100 111 109 97 105 110 34 58 34 119 119 119 46 98 97 105 100 117 46 99 111 109 63 110 97 109 101 61 49 38 105 100 61 49 34 44 34 110 97 109 101 34 58 34 49 49 49 34 125 10]最后多了一个 0010,换行符。trim 掉就一样了
h.Write(bytes.TrimSpace(byteBuf.Bytes()))
fmt.Println(hex.EncodeToString(h.Sum(nil)))
06820973e7b8d3acdb4763264a803620 -
資深大佬 : janxin@also24 原因在于 API 网关可能最开始没支持这玩意
-
資深大佬 : also24@janxin #9
那也可以通过对整个 http body 进行 hash,签名放进 header 的方式来处理。或者将原有 body 整个包装进一个 JSON String 字段来解决,都可以避免字段乱序或序列化方式不统一造成的问题。
-
資深大佬 : shawndevprettyprinted 设置不同
-
資深大佬 : jifengg我就喜欢对整个 body 签名的这种,不用管什么参数排序的。