anti_repeat_service.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. """
  2. Anti-repeat call attack service
  3. """
  4. import time
  5. from typing import Tuple
  6. from app.core.redis_cache import redis_cache
  7. from app.core.logger import logger
  8. class AntiRepeatService:
  9. """Anti-repeat call attack service"""
  10. @staticmethod
  11. async def check_and_set_repeat_lock(action: str, identifier: str, lock_duration: int = 5) -> Tuple[bool, str]:
  12. """
  13. Check and set repeat call lock
  14. Args:
  15. action: Action type (login, register, unbind, recharge)
  16. identifier: Identifier (usually username)
  17. lock_duration: Lock duration in seconds, default 5
  18. Returns:
  19. tuple: (allow_call, error_message)
  20. """
  21. try:
  22. # Generate lock key
  23. lock_key = f"repeat_lock:{action}:{identifier}"
  24. # Check if lock exists
  25. exists = await redis_cache.exists(lock_key)
  26. if exists:
  27. return False, f"Operation too frequent, please try again after {lock_duration} seconds"
  28. # Set lock
  29. success = await redis_cache.set(lock_key, {"timestamp": int(time.time())}, lock_duration)
  30. if not success:
  31. logger.warning(f"Failed to set repeat call lock: {action}:{identifier}")
  32. # Allow call even if setting fails (graceful degradation)
  33. return True, ""
  34. logger.debug(f"Successfully set repeat call lock: {action}:{identifier}, duration {lock_duration} seconds")
  35. return True, ""
  36. except Exception as e:
  37. logger.exception(f"Failed to check repeat call lock: {action}:{identifier}")
  38. # Allow call when exception occurs (graceful degradation)
  39. return True, ""
  40. # Global instance
  41. anti_repeat_service = AntiRepeatService()