email-verification-rate-limit.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package middleware
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "one-api/common"
  7. "time"
  8. "github.com/gin-gonic/gin"
  9. )
  10. const (
  11. EmailVerificationRateLimitMark = "EV"
  12. EmailVerificationMaxRequests = 2 // 30秒内最多2次
  13. EmailVerificationDuration = 30 // 30秒时间窗口
  14. )
  15. func redisEmailVerificationRateLimiter(c *gin.Context) {
  16. ctx := context.Background()
  17. rdb := common.RDB
  18. key := "emailVerification:" + EmailVerificationRateLimitMark + ":" + c.ClientIP()
  19. listLength, err := rdb.LLen(ctx, key).Result()
  20. if err != nil {
  21. fmt.Println("Redis限流检查失败:", err.Error())
  22. c.Status(http.StatusInternalServerError)
  23. c.Abort()
  24. return
  25. }
  26. if listLength < EmailVerificationMaxRequests {
  27. rdb.LPush(ctx, key, time.Now().Format(timeFormat))
  28. rdb.Expire(ctx, key, time.Duration(EmailVerificationDuration)*time.Second)
  29. c.Next()
  30. return
  31. }
  32. c.JSON(http.StatusTooManyRequests, gin.H{
  33. "success": false,
  34. "message": fmt.Sprintf("发送过于频繁,请等待 %d 秒后再试", EmailVerificationDuration),
  35. })
  36. c.Abort()
  37. }
  38. func memoryEmailVerificationRateLimiter(c *gin.Context) {
  39. key := EmailVerificationRateLimitMark + ":" + c.ClientIP()
  40. if !inMemoryRateLimiter.Request(key, EmailVerificationMaxRequests, EmailVerificationDuration) {
  41. c.JSON(http.StatusTooManyRequests, gin.H{
  42. "success": false,
  43. "message": "发送过于频繁,请稍后再试",
  44. })
  45. c.Abort()
  46. return
  47. }
  48. c.Next()
  49. }
  50. func EmailVerificationRateLimit() gin.HandlerFunc {
  51. return func(c *gin.Context) {
  52. if common.RedisEnabled {
  53. redisEmailVerificationRateLimiter(c)
  54. } else {
  55. inMemoryRateLimiter.Init(common.RateLimitKeyExpirationDuration)
  56. memoryEmailVerificationRateLimiter(c)
  57. }
  58. }
  59. }