我正在尝试使用 golang 和 Google App Engine 设置 MS Teams 传出 Webhook(使用
gcloud app deploy
部署):
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
var secret string = "THIS_IS_A_SECRET"
func handleWebhook(w http.ResponseWriter, r *http.Request) {
fmt.Println("Webhook endpoint hit")
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Can't read request body", http.StatusBadRequest)
return
}
fmt.Println("Received webhook request:", string(body))
// Log the request body for debugging
fmt.Printf("Request Body: %s\n", string(body))
// Generate HMAC token from the request body
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(body)
expectedMAC := mac.Sum(nil)
expectedMACBase64 := base64.StdEncoding.EncodeToString(expectedMAC)
// Get the HMAC token from the request header
authHeader := r.Header.Get("Authorization")
if !strings.HasPrefix(authHeader, "HMAC ") {
fmt.Println("Invalid Authorization header")
http.Error(w, "Invalid Authorization header", http.StatusUnauthorized)
return
}
providedMACBase64 := strings.TrimPrefix(authHeader, "HMAC ")
// Compare the generated HMAC token with the provided one
if !hmac.Equal([]byte(providedMACBase64), []byte(expectedMACBase64)) {
fmt.Println("Invalid HMAC token")
fmt.Println("Expected HMAC token:", expectedMACBase64)
fmt.Println("Provided HMAC token:", providedMACBase64)
http.Error(w, "Invalid HMAC token", http.StatusUnauthorized)
return
} else {
fmt.Println("Authenticated: Valid HMAC token")
}
// Create a response in the format expected by Microsoft Teams
response := map[string]string{
"type": "message",
"text": "Webhook received successfully",
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}
func main() {
http.HandleFunc("/teams-webhook", handleWebhook)
http.ListenAndServe(":8080", nil)
}
但是,预期的 HMAC 和提供的 HMAC 总是不同的。我想我的HMAC算法一定有问题。有人知道这里出了什么问题吗?
好吧...原来我忘记解码Base64编码的密钥了:
[]byte(secret)
> base64.StdEncoding.DecodeString(secret)