| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- import uuid
- import base64
- import io
- from captcha.image import ImageCaptcha
- from app.core.cache import redis_client
- from app.core.config import settings
- class CaptchaService:
- @staticmethod
- def generate_captcha() -> dict:
- """
- Generates a captcha image, stores the code in Redis, and returns ID + B64 Image.
- """
- image = ImageCaptcha(width=280, height=90)
- # Generate 4 character code
- import random
- import string
- code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
-
- data = image.generate(code)
-
- # Create a unique ID
- captcha_id = str(uuid.uuid4())
-
- # Store in Redis: CAPTCHA:{uuid} -> code
- key = f"CAPTCHA:{captcha_id}"
- redis_client.setex(key, settings.CAPTCHA_EXPIRE_SECONDS, code)
-
- # Encode image to base64
- base64_image = base64.b64encode(data.getvalue()).decode('utf-8')
-
- return {
- "captcha_id": captcha_id,
- "image": f"data:image/png;base64,{base64_image}",
- "expire_seconds": settings.CAPTCHA_EXPIRE_SECONDS
- }
- @staticmethod
- def verify_captcha(captcha_id: str, code: str) -> bool:
- """
- Verifies the captcha code. Deletes the key after check (one-time use).
- """
- if not captcha_id or not code:
- return False
-
- key = f"CAPTCHA:{captcha_id}"
- stored_code = redis_client.get(key)
-
- if not stored_code:
- return False
-
- # Delete immediately to prevent replay
- redis_client.delete(key)
-
- return stored_code.upper() == code.upper()
|