package middleware import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "errors" "github.com/gin-gonic/gin" "gogs.baozhida.cn/zoie/OAuth-core/pkg/response" "net/http" "strconv" "time" ) const apiKeyHeader = "X-API-KEY" const apiSignatureHeader = "X-API-SIGNATURE" const apiTimestampHeader = "X-API-TIMESTAMP" // 这些 API Key 和 Secret 应该存储在安全的存储中,例如数据库或配置文件 var validAPIKeys = map[string]string{ "01HsBYiG": "A8CDJ1GQW4XNB3SZY7PKT92R6LQV8FW5", } // 验证签名是否有效 func isValidSignature(apiKey, signature, timestamp string) bool { // 使用提供的 API Key 查找对应的 API Secret secret, ok := validAPIKeys[apiKey] if !ok { return false } // 计算签名,签名内容是 "apiKey + timestamp" message := apiKey + timestamp mac := hmac.New(sha256.New, []byte(secret)) mac.Write([]byte(message)) expectedSignature := hex.EncodeToString(mac.Sum(nil)) // 验证客户端提供的签名是否与预期签名匹配 return hmac.Equal([]byte(signature), []byte(expectedSignature)) } // AuthCheckRole 权限检查中间件 func ApiKeyAuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { apiKey := c.GetHeader(apiKeyHeader) signature := c.GetHeader(apiSignatureHeader) timestamp := c.GetHeader(apiTimestampHeader) // 检查 API Key, 签名和时间戳是否存在 if apiKey == "" || signature == "" || timestamp == "" { err := errors.New("API Key, Signature, and Timestamp required") response.Error(c, http.StatusUnauthorized, err, err.Error()) return } // 校验请求的签名是否有效 if !isValidSignature(apiKey, signature, timestamp) { err := errors.New("Invalid Signature") response.Error(c, http.StatusForbidden, err, err.Error()) return } // 校验时间戳是否在合理范围内(防止重放攻击) sec, _ := strconv.ParseInt(timestamp, 10, 64) reqTime := time.Unix(sec, 0) if time.Since(reqTime) > 5*time.Minute { err := errors.New("Request too old or invalid timestamp") response.Error(c, http.StatusForbidden, err, err.Error()) return } // 如果鉴权成功,继续处理请求 c.Next() return } }