Trong bài viết này, chúng tôi đã cố gắng trả lời tất cả những câu hỏi quan trọng. Bước đầu tiên để bắt đầu giải quyết vấn đề là xác định hệ thống bảo mật nào đang được sử dụng. Để làm điều đó, bạn có thể tham khảo danh sách các captcha và hệ thống chống bot phổ biến, trong đó có các ví dụ minh họa và những dấu hiệu chính giúp bạn nhanh chóng nhận biết mình đang làm việc với giải pháp nào.
Nếu bạn phát hiện trang web của mình đang sử dụng ComplexImage, bước tiếp theo là tìm hiểu chi tiết hơn về các đặc tính và cách hoạt động của nó. Ngay trong bài viết này, bạn cũng có thể xem hướng dẫn tích hợp hệ thống ComplexImage để hiểu đầy đủ cách nó vận hành trên trang web của bạn. Điều đó giúp bạn không chỉ nắm rõ lớp bảo vệ hiện tại mà còn lập kế hoạch bảo trì một cách hợp lý.
Làm việc với CapMonster Cloud qua API thường gồm các bước:
type - ComplexImageTask
class - recognition
imagesBase64 - mảng hình ảnh ở định dạng base64. Ví dụ: [“/9j/4AAQSkZJRgABAQEAAAAAAAD…”];
Task (trong metadata) - tên nhiệm vụ (ví dụ: dli).
https://api.capmonster.cloud/createTask{
"clientKey": "API_KEY",
"task": {
"type": "ComplexImageTask",
"class": "recognition",
"imagesBase64": [
"base64"
],
"metadata": {
"Task": "dli" // thay bằng nhiệm vụ cần thiết, danh sách module có sẵn có thể tìm thấy tại https://docs.capmonster.cloud/docs/captchas/ComplexImageTask-Recognition/
}
}
}
{
"errorId":0,
"taskId":407533072
}https://api.capmonster.cloud/getTaskResult{
"clientKey":"API_KEY",
"taskId": 407533072
}
{
"solution":
{
"answer": "1",
"metadata": {
"AnswerType": "Text"
}
},
"cost": 0.0003,
"status": "ready",
"errorId": 0,
"errorCode": null,
"errorDescription": null
}
// npm install playwright @zennolab_com/capmonstercloud-client
// npx playwright install chromium
import { chromium } from 'playwright';
import { CapMonsterCloudClientFactory, ClientOptions, ComplexImageTaskRecognitionRequest } from '@zennolab_com/capmonstercloud-client';
const API_KEY = "YOUR_API_KEY";
const TARGET_URL = "https://example.com/captcha-page";
async function solveComplexImageTaskPlaywright() {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(TARGET_URL);
// Tìm hình ảnh CAPTCHA
const captchaHandle = await page.$('#captcha'); // thay bằng selector thực tế
const captchaBase64 = await captchaHandle.evaluate(img => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
return canvas.toDataURL('image/png').split(',')[1];
});
console.log("Captcha base64:", captchaBase64.substring(0, 50) + "...");
const cmcClient = CapMonsterCloudClientFactory.Create(
new ClientOptions({ clientKey: API_KEY })
);
// Gửi CAPTCHA để nhận dạng
const citRecognitionRequest = new ComplexImageTaskRecognitionRequest({
imagesBase64: [captchaBase64],
metaData: { Task: 'oocl_rotate' } // thay bằng loại CAPTCHA của bạn
});
const result = await cmcClient.Solve(citRecognitionRequest);
console.log("Solution received:", result);
// Xử lý kết quả
const solution = result.solution;
if (!solution) {
console.error("No solution received");
return;
}
if (solution.metadata?.AnswerType === "Coordinate") {
// CAPTCHA có tọa độ
const box = await captchaHandle.boundingBox();
for (const point of solution.answer) {
const clickX = box.x + point.X;
const clickY = box.y + point.Y;
console.log(`Clicking at: (${clickX}, ${clickY})`);
await page.mouse.click(clickX, clickY);
}
} else if (solution.metadata?.AnswerType === "Grid") {
// CAPTCHA Grid (mảng true/false)
const box = await captchaHandle.boundingBox();
const gridItems = await page.$$('#captcha_grid div'); // thay bằng selector các phần tử lưới
const answers = solution.answer;
for (let i = 0; i < answers.length; i++) {
if (answers[i] && gridItems[i]) {
const itemBox = await gridItems[i].boundingBox();
const clickX = itemBox.x + itemBox.width / 2;
const clickY = itemBox.y + itemBox.height / 2;
console.log(`Clicking grid item ${i} at: (${clickX}, ${clickY})`);
await page.mouse.click(clickX, clickY);
}
}
} else {
console.warn("Unknown captcha solution type:", solution.metadata?.AnswerType);
}
// Nhấn nút xác nhận (nếu có)
await page.click('#submit_button'); // thay bằng selector nút thực tế
console.log("Captcha solved.");
}
solveComplexImageTaskPlaywright().catch(console.error);
1. Tạo CAPTCHA trên máy chủ.
2. Gửi CAPTCHA đến client
<!--CAPTCHA lưới hình ảnh-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Grid CAPTCHA Demo</title>
<style>
#captchaGrid {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-gap: 10px;
margin-bottom: 10px;
}
.grid-item {
width: 100px;
height: 100px;
background-color: #eee;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: 2px solid transparent;
}
.grid-item.selected {
border-color: blue;
}
</style>
</head>
<body>
<h1>Grid CAPTCHA Demo</h1>
<div id="captchaGrid"></div>
<button id="submitBtn">Submit</button>
<button id="refreshBtn">Refresh CAPTCHA</button>
<p id="result"></p>
<script>
let captchaId;
let answers = []; // mảng true/false theo lượt click
async function loadCaptcha() {
const res = await fetch('/captcha'); // server phải trả JSON với captchaId và mảng hình ảnh base64
const data = await res.json();
captchaId = data.captchaId;
answers = new Array(data.images.length).fill(false);
const grid = document.getElementById('captchaGrid');
grid.innerHTML = '';
data.images.forEach((imgBase64, i) => {
const div = document.createElement('div');
div.className = 'grid-item';
div.style.backgroundImage = `url('data:image/png;base64,${imgBase64}')`;
div.style.backgroundSize = 'cover';
div.addEventListener('click', () => {
answers[i] = !answers[i];
div.classList.toggle('selected', answers[i]);
});
grid.appendChild(div);
});
document.getElementById('result').textContent = '';
}
document.getElementById('refreshBtn').addEventListener('click', loadCaptcha);
document.getElementById('submitBtn').addEventListener('click', async () => {
const res = await fetch('/captcha/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ captchaId, answer: answers })
});
const data = await res.json();
document.getElementById('result').textContent = data.success ? 'Captcha passed!' : 'Captcha failed, try again.';
if (!data.success) loadCaptcha();
});
// load CAPTCHA khi bắt đầu
loadCaptcha();
</script>
</body>
</html>
3. Người dùng nhập câu trả lời
4. Gửi câu trả lời lên server:
5. Kiểm tra trên server
<?php
session_start();
// TTL CAPTCHA (giây)
define('CAPTCHA_TTL', 300); // 5 phút
// Tạo hình ảnh ngẫu nhiên
function generateCaptchaImage($text = null) {
$width = 100;
$height = 100;
if (!$text) {
$text = substr(str_shuffle('ABCDEFGHJKLMNPQRSTUVWXYZ23456789'), 0, 2);
}
$image = imagecreatetruecolor($width, $height);
// nền
$bgColor = imagecolorallocate($image, rand(180, 255), rand(180, 255), rand(180, 255));
imagefilledrectangle($image, 0, 0, $width, $height, $bgColor);
// văn bản
$textColor = imagecolorallocate($image, 0, 0, 0);
$fontSize = 15;
$fontFile = __DIR__ . '/Arial.ttf'; // đường dẫn font TTF
if (file_exists($fontFile)) {
imagettftext($image, $fontSize, rand(-20,20), 10, 50, $textColor, $fontFile, $text);
} else {
imagestring($image, 5, 10, 40, $text, $textColor);
}
ob_start();
imagepng($image);
$imgData = ob_get_clean();
imagedestroy($image);
return base64_encode($imgData);
}
// Tạo Grid CAPTCHA
function generateGridCaptcha() {
$numImages = 9; // 3x3
$images = [];
$solution = [];
for ($i = 0; $i < $numImages; $i++) {
// Giải ngẫu nhiên, đúng hoặc sai (ví dụ)
$isCorrect = rand(0,1) === 1;
$solution[] = $isCorrect;
// Tạo hình ảnh (có thể thêm đối tượng cho CAPTCHA thực)
$text = $isCorrect ? 'OK' : 'NO';
$images[] = generateCaptchaImage($text);
}
return ['images' => $images, 'solution' => $solution];
}
// Endpoint tạo CAPTCHA
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/captcha') {
$captchaId = uniqid('captcha_', true);
$gridCaptcha = generateGridCaptcha();
$_SESSION['captchas'][$captchaId] = [
'solution' => $gridCaptcha['solution'],
'timestamp' => time()
];
header('Content-Type: application/json');
echo json_encode([
'captchaId' => $captchaId,
'images' => $gridCaptcha['images']
]);
exit;
}
// Endpoint kiểm tra CAPTCHA
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['REQUEST_URI'] === '/captcha/verify') {
$data = json_decode(file_get_contents('php://input'), true);
$captchaId = $data['captchaId'] ?? '';
$answer = $data['answer'] ?? [];
if (!isset($_SESSION['captchas'][$captchaId])) {
echo json_encode(['success' => false, 'message' => 'Captcha expired or not found']);
exit;
}
$captcha = $_SESSION['captchas'][$captchaId];
// kiểm tra TTL
if (time() - $captcha['timestamp'] > CAPTCHA_TTL) {
unset($_SESSION['captchas'][$captchaId]);
echo json_encode(['success' => false, 'message' => 'Captcha expired']);
exit;
}
// kiểm tra mảng true/false
$success = $captcha['solution'] === $answer;
// xóa CAPTCHA sau kiểm tra
unset($_SESSION['captchas'][$captchaId]);
echo json_encode(['success' => $success]);
exit;
}
// 404
http_response_code(404);
echo 'Not found';
6. Hành động tiếp theo
Bổ sung
Thực hiện kiểm tra tải (ví dụ: k6 hoặc JMeter) — khi nhiều request:
Nếu bạn gặp site có CAPTCHA hoặc hệ thống bảo vệ đã cài và không có quyền truy cập code — không sao! Xác định công nghệ tương đối dễ dàng. Để kiểm tra chính xác, dùng CapMonster Cloud trong môi trường thử nghiệm tách biệt để đảm bảo xử lý token và logic xác thực hoạt động đúng.
Với CAPTCHA hình ảnh — chỉ cần nhận dạng hệ thống, nghiên cứu hành vi và đảm bảo bảo vệ hoạt động. Bài viết hướng dẫn cách xác định CAPTCHA hình ảnh (ComplexImage) và cách tích hợp hoặc cấu hình lại, giúp bạn quản lý và kiểm soát bảo vệ.