解析 payload 后发现,默认情况下它是 base64 编码的,但对该 base64 编码后的 payload 进行 256SHA 哈希计算的结果不正确。我使用的是原始帖子中的示例密钥和 URL。
以下代码产生的输出如下:
payloadURL = bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=
sig = 2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56
payloadRaw = nonce=cb68251eefb5211e58c00ff1395f0c0b
payload256 = KCiqKYmXIrNaLxkdNO+bPOaV4Obu7EfetG1YjXDHy1Y=
我的代码:
testURL := "http://www.example.com/discourse/sso?sso=bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI%3D%0A\u0026sig=2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56"
ssoSecret := "d836444a9e4084d5b224a60c208dce14"
// 从 URL 查询参数中获取 payload 和 sig
u, err := url.Parse(testURL)
if err != nil {
log.Fatal(err)
}
q := u.Query()
payloadURL := strings.Trim(fmt.Sprint(q["sso"]), "=[]")
sig := strings.Trim(fmt.Sprint(q["sig"]), "[]")
fmt.Printf("payloadURL = %s\n", payloadURL)
fmt.Printf("sig = %s\n", sig)
// 从 base64 版本中获取原始 payload
payloadRaw, err := base64.StdEncoding.DecodeString(payloadURL)
if err != nil {
log.Fatal(err)
}
fmt.Printf("payloadRaw = %s\n", payloadRaw)
key := []byte(ssoSecret)
message := []byte(payloadURL)
hash := hmac.New(sha256.New, key)
hash.Write(message)
payload256 := base64.StdEncoding.EncodeToString(hash.Sum(nil))
if err != nil {
log.Fatal(err)
}
fmt.Printf("payload256 = %s\n", payload256)
// sig 是十六进制编码的,因此将哈希后的 payload 也进行十六进制编码以便比较。
//hashAsString := hex.EncodeToString(hash.Sum(nil))
// 将 payload 的十六进制编码哈希值与十六进制编码的 sig 进行比较
if strings.Compare(payload256, sig) != 0 {
log.Fatal(err)
}
更新:我在将生成的 HMAC-SHA256 哈希值编码为十六进制后修复了此问题(签名也是十六进制编码的)。另请参阅 这篇帖子,其中指出 SSO 指南中的示例有误。因此,我修改了以下代码:
key := []byte(ssoSecret)
message := []byte(payloadURL)
hash := hmac.New(sha256.New, key)
hash.Write(message)
payload256 := hex.EncodeToString(hash.Sum(nil))
if err != nil {
log.Fatal(err)
}