go map 按字典升序排序后转 JSON md5 与 PHP 不一致

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 之后作为签名参数用

  • 資深大佬 : marquina

    json 在我这个 pythoner 眼里就是一个 dict,我也从来不会对 json 序列化、反序列化时 key 的顺序有任何期待,更别提算 md5 这种操作了

  • 資深大佬 : Nick66

    @marquina 接手项目的时候就是这样,我也无法改变,只能想办法解决。

  • 資深大佬 : haiyang416

    @Nick66 https://github.com/golang/go/commit/6f25f1d4c901417af1da65e41992d71c30f64f8f

    strings.Trim 一下。

  • 資深大佬 : chinvo

    签名的正确玩法是对 http body 签名,签名结果放到 header 里

    这样就不涉及排序问题

  • 資深大佬 : Nick66

    @haiyang416 感谢,解决了。

  • 資深大佬 : Vegetable

    byteBuf.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 字段来解决,都可以避免字段乱序或序列化方式不统一造成的问题。

  • 資深大佬 : shawndev

    prettyprinted 设置不同

  • 資深大佬 : jifengg

    我就喜欢对整个 body 签名的这种,不用管什么参数排序的。

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论