Hướng Dẫn Thực Hành

Cache token CAPTCHA và tái sử dụng có kiểm soát trong QA

Phạm vi an toàn: Chỉ áp dụng cho môi trường QA, staging hoặc pre-production do bạn sở hữu hoặc được uỷ quyền — không dùng cho bên thứ ba.

Bộ test QA chạy lại luồng đăng nhập có reCAPTCHA v2 hàng trăm lần mỗi ngày, và request in.php cứ tăng đều dù code không đổi? Nguyên nhân thường là mỗi lần test đều gửi task mới thay vì tái dùng token còn hợp lệ. Cache token trong khung hợp lệ chính thức — khoảng 120 giây với reCAPTCHA v2/v3, khoảng 300 giây với Turnstile — cắt giảm số task mà kết quả test vẫn đáng tin cậy.

Ví dụ nhanh: test reCAPTCHA v2 trên staging bằng Python

Luồng tối thiểu để test một widget reCAPTCHA v2 trên staging qua CaptchaAI: gửi task rồi polling kết quả.

import os
import requests

API_KEY = os.environ['CAPTCHAAI_KEY']
QA_PAGE_URL = os.environ['QA_PAGE_URL']  # ví dụ https://staging.example.com/qa-login
QA_SITE_KEY = os.environ['QA_SITE_KEY']


def submit_qa_recaptcha() -> str:
    payload = {
        'clientKey': API_KEY,
        'task': {
            'type': 'NoCaptchaTaskProxyless',
            'websiteURL': QA_PAGE_URL,
            'websiteKey': QA_SITE_KEY,
        },
    }
    response = requests.post(
        'https://api.captchaai.com/createTask',
        json=payload,
        timeout=30,
    )
    response.raise_for_status()
    return response.json()['taskId']


def fetch_qa_result(task_id: str) -> dict:
    payload = {'clientKey': API_KEY, 'taskId': task_id}
    response = requests.post(
        'https://api.captchaai.com/getTaskResult',
        json=payload,
        timeout=30,
    )
    response.raise_for_status()
    return response.json()

Vì sao QA nên cache token thay vì giải lại mỗi lần

Một đội QA outsourcing tại TP.HCM chạy CI cho form đăng nhập có reCAPTCHA v2 hơn 300 lần/ngày trước mỗi lần release; mỗi request in.php thừa đều cộng dồn vào số thread đang dùng. Test case cùng sitekey và pageurl dùng lại được một token còn hạn thay vì tự giải riêng — miễn backend QA không bắt buộc token duy nhất cho từng request.

Khoá cache và TTL theo từng loại CAPTCHA

Khoá theo sitekey, pageurl và qa_case

Khoá cache theo bộ ba (sitekey, pageurl, qa_case). qa_case phân biệt các kịch bản trên cùng trang — ví dụ đăng nhập hợp lệ và sai mật khẩu — tránh test case này dùng nhầm token đã bị test case khác làm mất hiệu lực.

TTL đề xuất theo loại CAPTCHA

Loại CAPTCHA Hạn token chính thức TTL cache đề xuất
reCAPTCHA v2 ~120 giây 100 giây
reCAPTCHA v3 ~120 giây 100 giây
Cloudflare Turnstile ~300 giây 240 giây

Đưa cache vào luồng gọi CaptchaAI

Trước khi gửi task mới tới in.php, kiểm tra cache; còn hạn thì dùng lại token ngay. Cache miss thì gửi task, polling res.php rồi ghi token mới vào cache. Nhiều CI runner song song thì dùng Redis (SETEX theo TTL) thay vì cache trong bộ nhớ từng tiến trình.

Checklist trước khi đưa vào CI

  • Phạm vi test giới hạn trong ứng dụng hoặc tài nguyên đã được uỷ quyền.
  • API key CaptchaAI nằm trong CI secret hoặc vault, không trong mã nguồn.
  • Mỗi lần chạy ghi thời gian gọi, mã trạng thái, và có backoff cho lỗi tạm thời.
  • Test tái lập được trên CI, không cần can thiệp thủ công.

Ghi log để chẩn đoán nhanh khi test fail

Ghi log có cấu trúc cho mỗi lần chạy: thời gian lấy token, mã trạng thái HTTP, ID task, độ sâu hàng đợi. Tách log theo môi trường và gắn một correlation id xuyên suốt các bước — ví dụ qua OpenTelemetry — để phát lại cả kịch bản từ một id duy nhất khi test fail giữa chừng.

Khắc phục sự cố thường gặp

Vấn đề Nguyên nhân Cách xử lý
Test không thấy widget Selector đổi hoặc trang load chậm Kiểm tra selector, tăng wait_for_selector
ERROR_NO_SLOT_AVAILABLE Hàng đợi đầy tạm thời Backoff trong pipeline nội bộ
Backend từ chối token cache Sai action, sitekey hoặc secret Đối chiếu cấu hình backend với staging

Câu hỏi thường gặp

Cache TTL có khác gì với giữ sẵn nhiều token để dùng dần không?

Có. Cache TTL chỉ giữ một token cho một (sitekey, pageurl, qa_case), đúng khung hợp lệ của loại CAPTCHA đó — không tích luỹ token cho nhu cầu tương lai.

Nhiều CI runner song song thì cache kiểu gì?

Dùng Redis thay vì cache trong bộ nhớ từng tiến trình, để mọi runner đọc cùng token còn hạn.

Lỗi tạm thời như ERROR_NO_SLOT_AVAILABLE hoặc mã 5xx thì xử lý sao?

Thử lại idempotent với backoff (1s, 2s, 4s) và giới hạn số lần. Lỗi xác thực kéo dài thì không nên thử lại tự động.

Hướng dẫn liên quan an toàn

Xác thực tích hợp CAPTCHA với CaptchaAI trong môi trường nội bộ của bạn.

Os comentários estão desativados para este artigo.