openapi.go 2.2 KB

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