openapi.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package middleware
  2. import (
  3. "cold-delivery/conf"
  4. "crypto/hmac"
  5. "crypto/sha256"
  6. "encoding/hex"
  7. "errors"
  8. "github.com/gin-gonic/gin"
  9. "gogs.baozhida.cn/zoie/OAuth-core/pkg/response"
  10. "net/http"
  11. "strconv"
  12. "time"
  13. )
  14. const apiKeyHeader = "X-API-KEY"
  15. const apiSignatureHeader = "X-API-SIGNATURE"
  16. const apiTimestampHeader = "X-API-TIMESTAMP"
  17. // 验证签名是否有效
  18. func isValidSignature(apiKey, signature, timestamp string) bool {
  19. // 使用提供的 API Key 查找对应的 API Secret
  20. if apiKey != conf.ExtConfig.OpenApi.ApiKey {
  21. return false
  22. }
  23. secret := conf.ExtConfig.OpenApi.Secret
  24. // 计算签名,签名内容是 "apiKey + timestamp"
  25. message := apiKey + timestamp
  26. mac := hmac.New(sha256.New, []byte(secret))
  27. mac.Write([]byte(message))
  28. expectedSignature := hex.EncodeToString(mac.Sum(nil))
  29. // 验证客户端提供的签名是否与预期签名匹配
  30. return hmac.Equal([]byte(signature), []byte(expectedSignature))
  31. }
  32. // AuthCheckRole 权限检查中间件
  33. func ApiKeyAuthMiddleware() gin.HandlerFunc {
  34. return func(c *gin.Context) {
  35. apiKey := c.GetHeader(apiKeyHeader)
  36. signature := c.GetHeader(apiSignatureHeader)
  37. timestamp := c.GetHeader(apiTimestampHeader)
  38. // 检查 API Key, 签名和时间戳是否存在
  39. if apiKey == "" || signature == "" || timestamp == "" {
  40. err := errors.New("API Key, Signature, and Timestamp required")
  41. response.Error(c, http.StatusUnauthorized, err, err.Error())
  42. return
  43. }
  44. // 校验请求的签名是否有效
  45. if !isValidSignature(apiKey, signature, timestamp) {
  46. err := errors.New("Invalid Signature")
  47. response.Error(c, http.StatusForbidden, err, err.Error())
  48. return
  49. }
  50. // 校验时间戳是否在合理范围内(防止重放攻击)
  51. sec, _ := strconv.ParseInt(timestamp, 10, 64)
  52. reqTime := time.Unix(sec, 0)
  53. if time.Since(reqTime) > 5*time.Minute {
  54. err := errors.New("Request too old or invalid timestamp")
  55. response.Error(c, http.StatusForbidden, err, err.Error())
  56. return
  57. }
  58. // 如果鉴权成功,继续处理请求
  59. c.Next()
  60. return
  61. }
  62. }