2025-09-12 17:12:02 +08:00
|
|
|
|
// Package util provide some utility functions
|
|
|
|
|
|
package util
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"crypto/hmac"
|
|
|
|
|
|
"crypto/sha256"
|
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"os"
|
|
|
|
|
|
"strings"
|
|
|
|
|
|
"time"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// GenerateClientToken define func of generate a secure token for client identification
|
2025-10-14 16:12:00 +08:00
|
|
|
|
func GenerateClientToken(host string, serviceName string, secretKey string) (string, error) {
|
|
|
|
|
|
finalSecretKey := secretKey
|
|
|
|
|
|
if finalSecretKey == "" {
|
|
|
|
|
|
finalSecretKey = os.Getenv("TOKEN_SECRET_KEY")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if finalSecretKey == "" {
|
|
|
|
|
|
return "", fmt.Errorf("TOKEN_SECRET_KEY environment variable not set and no key provided in parameters")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-12 17:12:02 +08:00
|
|
|
|
uniqueID := fmt.Sprintf("%d", time.Now().UnixNano())
|
|
|
|
|
|
clientInfo := fmt.Sprintf("host=%s;service=%s;id=%s", host, serviceName, uniqueID)
|
|
|
|
|
|
|
2025-10-14 16:12:00 +08:00
|
|
|
|
mac := hmac.New(sha256.New, []byte(finalSecretKey))
|
2025-09-12 17:12:02 +08:00
|
|
|
|
mac.Write([]byte(clientInfo))
|
|
|
|
|
|
signature := mac.Sum(nil)
|
|
|
|
|
|
|
|
|
|
|
|
token := fmt.Sprintf("%s.%s",
|
|
|
|
|
|
base64.URLEncoding.EncodeToString([]byte(clientInfo)),
|
|
|
|
|
|
base64.URLEncoding.EncodeToString(signature))
|
|
|
|
|
|
|
|
|
|
|
|
return token, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// verifyClientToken define func of verify the client token
|
|
|
|
|
|
func verifyClientToken(token string, secretKey string) (bool, string, error) {
|
|
|
|
|
|
parts := strings.Split(token, ".")
|
|
|
|
|
|
if len(parts) != 2 {
|
|
|
|
|
|
return false, "", fmt.Errorf("invalid token format")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
encodedClientInfo := parts[0]
|
|
|
|
|
|
encodedSignature := parts[1]
|
|
|
|
|
|
|
|
|
|
|
|
clientInfoBytes, err := base64.URLEncoding.DecodeString(encodedClientInfo)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return false, "", fmt.Errorf("failed to decode client info: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
signatureBytes, err := base64.URLEncoding.DecodeString(encodedSignature)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return false, "", fmt.Errorf("failed to decode signature: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mac := hmac.New(sha256.New, []byte(secretKey))
|
|
|
|
|
|
mac.Write(clientInfoBytes)
|
|
|
|
|
|
expectedSignature := mac.Sum(nil)
|
|
|
|
|
|
|
|
|
|
|
|
if !hmac.Equal(signatureBytes, expectedSignature) {
|
|
|
|
|
|
return false, "", nil // 签名不匹配,token 无效
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
clientInfo := string(clientInfoBytes)
|
|
|
|
|
|
return true, clientInfo, nil
|
|
|
|
|
|
}
|