In dit artikel hebben we geprobeerd antwoord te geven op alle belangrijke vragen. De eerste stap bij het oplossen van het vraagstuk is vaststellen welk beveiligingssysteem wordt gebruikt. Daarvoor kun je de lijst met populaire captcha’s en anti-botbeveiligingssystemen raadplegen, met visuele voorbeelden en kernkenmerken die je helpen snel te bepalen waarmee je te maken hebt.
Als je ontdekt dat je website TenDI (Tencent) gebruikt, is de volgende stap om de eigenschappen en werking ervan uitgebreider te bestuderen. In dit artikel vind je ook een handleiding voor het integreren van TenDI (Tencent), zodat je volledig begrijpt hoe het systeem op je website werkt. Zo kun je niet alleen de huidige bescherming beter doorgronden, maar ook het onderhoud ervan goed plannen.
Werken met CapMonster Cloud via de API bestaat doorgaans uit de volgende stappen:
type - CustomTask
class - TenDI
websiteURL - Het adres van de pagina waar de captcha wordt opgelost.
websiteKey - captchaAppId. Bijvoorbeeld "websiteKey": "189123456" — unieke parameter voor jouw website
captchaUrl (in metadata) - Link naar het captcha-script. Meestal eindigt het op TCaptcha.js of TCaptcha-global.js;
websiteURL - Het adres van de pagina waar de captcha wordt opgelost;
userAgent (optioneel) - Browser User-Agent. Stuur alleen een actuele UA van Windows.
https://api.capmonster.cloud/createTask
{
"clientKey": "API_KEY",
"task": {
"type": "CustomTask",
"class": "TenDI",
"websiteURL": "https://example.com",
"websiteKey": "189123456",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
"metadata": {
"captchaUrl": "https://global.captcha.example.com/TCaptcha-global.js"
}
}
}
{
"errorId":0,
"taskId":407533072
}https://api.capmonster.cloud/getTaskResult{
"clientKey":"API_KEY",
"taskId": 407533072
}
{
"errorId":0,
"status":"ready",
"solution": {
"data": {
"randstr": "@EcL",
"ticket": "tr03lHUhdnuW3neJZu.....7LrIbs*"
},
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"
}
}
}
// npx playwright install chromium
import { chromium } from 'playwright';
import { CapMonsterCloudClientFactory, ClientOptions, TenDIRequest } from '@zennolab_com/capmonstercloud-client';
// Vervang door je eigen waarden
const API_KEY = "YOUR_API_KEY";
const WEBSITE_URL = "https://example.com";
async function solveTenDIOnPage() {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
// 1. Open de pagina
await page.goto(WEBSITE_URL, { waitUntil: 'networkidle' });
// 2. Wacht tot de captcha verschijnt (bijv. input of iframe)
await page.waitForSelector('#tendi_response, iframe[src*="tendi"], input[name="tendi_response"]', { timeout: 15000 });
// Indien nodig kun je de websiteKey van de pagina halen
const WEBSITE_KEY = await page.evaluate(() => {
// Voorbeeld: sitekey kan in een data-attribuut of globale variabele staan
const el = document.querySelector('#tendi_response') || document.querySelector('div[data-sitekey]');
return el?.getAttribute('data-sitekey') || window.TenDI_siteKey || "183268248";
});
console.log("Website key detected:", WEBSITE_KEY);
const client = CapMonsterCloudClientFactory.Create(
new ClientOptions({ clientKey: API_KEY })
);
// 3. Maak een TenDI-taak aan
const tenDIRequest = new TenDIRequest({
websiteURL: page.url(),
websiteKey: WEBSITE_KEY,
});
const balance = await client.getBalance();
console.log("Balance:", balance);
// 4. Los de captcha op
const solution = await client.Solve(tenDIRequest);
console.log("Solution:", solution);
const { ticket, randstr } = solution.solution.data;
// 5. Methoden om het resultaat in te voegen
await page.evaluate(({ ticket, randstr }) => {
// Invoegen in input
const inputSelectors = ['#tendi_response', 'input[name="tendi_response"]', 'input[type="hidden"]'];
let inserted = false;
for (const sel of inputSelectors) {
const input = document.querySelector(sel);
if (input) {
input.value = ticket;
input.dispatchEvent(new Event('input', { bubbles: true }));
const form = input.closest('form');
if (form) form.submit();
inserted = true;
break;
}
}
// JS callback-functie
if (typeof window.onCaptchaSolved === 'function') {
window.onCaptchaSolved(ticket, randstr);
inserted = true;
}
// Als er geen input of callback is
if (!inserted) {
window._tenDITicket = ticket;
window._tenDIRandStr = randstr;
console.log("Ticket and randstr saved to window._tenDITicket and window._tenDIRandStr");
}
}, { ticket, randstr });
await page.waitForTimeout(5000);
await browser.close();
}
solveTenDIOnPage().catch(console.error);
Je ontvangt twee parameters: CaptchaAppId en AppSecretKey. Deze gebruik je op zowel frontend als server.
Bij klikken verschijnt de captcha en na oplossing wordt het resultaat in de console getoond.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Captcha Example</title>
// Verplichte JS captcha-lading
<script src="https://ca.turing.captcha.qcloud.com/TJNCaptcha-global.js"></script>
</head>
<body>
<div id="cap_iframe"></div>
<button id="CaptchaId">Verification</button>
<script>
// Resultaatverwerking
function callback(res) {
console.log("callback:", res);
if (res.ret === 0) {
// Verificatie geslaagd
const text = `[randstr] ${res.randstr} | [ticket] ${res.ticket}`;
const input = document.createElement("input");
input.value = text;
document.body.appendChild(input);
input.select();
document.execCommand("Copy");
document.body.removeChild(input);
alert("Ticket en randstr gekopieerd naar klembord.");
}
}
// Foutafhandeling bij captcha-scriptladen
function loadErrorCallback() {
const appid = "CaptchaAppId";
const ticket = `trerror_1001_${appid}_1769260299`;
callback({
ret: 0,
randstr: "@" + Math.random().toString(36).slice(2),
ticket,
errorCode: 1001,
errorMessage: "jsload_error",
});
}
window.onload = function () {
document.getElementById("CaptchaId").onclick = function () {
try {
const captcha = new TencentCaptcha(
document.getElementById("cap_iframe"),
"Your CaptchaAppId",
callback,
{}
);
captcha.show();
} catch (e) {
loadErrorCallback();
}
};
};
</script>
</body>
</html>
Hoe de integratie werkt
Stap 1: Laad de JS van de captcha
Het script moet dynamisch worden geladen:
<script src="https://ca.turing.captcha.qcloud.com/TJNCaptcha-global.js"></script>Bij niet-standaard laden of cachen kan de captcha verkeerd werken.
Stap 2: Maak TencentCaptcha-object aan
Na JS-laden verschijnt een globale klasse:
<script src="new TencentCaptcha(domElement, CaptchaAppId, callback, options);"></script>Parameters:
domElement - Container waarin checkbox/iframe wordt geplaatst
CaptchaAppId - Je ID
callback - Wat te doen na verificatie
options - Uiterlijke instellingen (optioneel)
Stap 3: Roep methode aan .show()
captcha.show();Toont captcha. Kan meerdere keren worden aangeroepen.
Stap 4: Verwerk resultaat
Callback ontvangt een object:
{
ret: 0, // 0 -- succes, 2 -- gebruiker sloot venster
ticket: "...", // vereist door server
randstr: "...", // ook vereist door server
errorCode: 1001, // als captcha niet geladen is
errorMessage: "..." // foutbericht
}Voer altijd secundaire verificatie van ticket uit op de server.
"Noodherstelmodus"
Als de captcha niet laadt (bijv. CDN niet beschikbaar), kan automatisch een 'noodticket' worden uitgegeven om bedrijfsprocessen niet te onderbreken.
Scenario:
trerror_<errorcode>_<appid>_<timestamp>AppId-encryptie (optioneel)
Voor maximale bescherming kan een versleutelde versie van AppId worden gebruikt in plaats van de open versie:
aidEncrypted = Base64(IV + AES256(AppId & timestamp & ttl))Benodigd:
Server-side encryptie voorbeeld (Python)
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64
def encrypt(plaintext, key, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
ciphertext = cipher.encrypt(pad(plaintext.encode(), AES.block_size))
return base64.b64encode(iv + ciphertext).decode("utf-8")Server-side validatie
Stap 1. API-toegang instellen
Krijg SecretId en SecretKey van je key management paneel (CAM / API Key Management). Nodig voor gesigneerde API-verzoeken.
Stap 2. API DescribeCaptchaResult aanroepen
Zodra de client ticket en randstr heeft geretourneerd, moet de server verzoek sturen:
Parameters:
CaptchaType - 9 (vaste waarde)
Ticket - string — ticket, terug van client
Randstr - string — randstr, terug van client
CaptchaAppId - je AppId
AppSecretKey - je geheime sleutel
UserIp - IP van gebruiker (aanbevolen)
Stap 3. Verwerk respons
API retourneert:
Als CaptchaCode === OK, wordt de gebruiker als geverifieerd beschouwd. Anders — weigeren.
Voorbeeld — ticket verificatie in Node.js
import { v20190722 as captcha } from "@tencentcloud/tencentcloud-sdk-nodejs";
const client = new captcha.Client({
credential: {
secretId: "YOUR_SECRET_ID",
secretKey: "YOUR_SECRET_KEY"
},
region: "ap-project", // regio indien nodig
});
async function verifyCaptcha(ticket, randstr, userIp) {
const params = {
CaptchaType: 9,
Ticket: ticket,
Randstr: randstr,
CaptchaAppId: YOUR_APP_ID,
AppSecretKey: "YOUR_APP_SECRET_KEY",
UserIp: userIp
};
const resp = await client.DescribeCaptchaResult(params);
const code = resp.Response.CaptchaCode;
return code === 0;
}Meer informatie over het aansluiten van Tencent CAPTCHA op je website vind je in de officiële documentatie.
Als je een website in beheer krijgt waarop al een captcha of een ander beveiligingssysteem is geïnstalleerd en je geen toegang hebt tot de code, is dat geen probleem! Het is vrij eenvoudig te bepalen welke technologie precies wordt gebruikt. Voor het controleren of alles correct werkt, kun je de herkenningsservice CapMonster Cloud in een geïsoleerde testomgeving gebruiken, zodat je zeker weet dat het tokenverwerkingsmechanisme en de validatielogica correct functioneren.
In het geval van TenDI (Tencent) is het voldoende om het systeem te herkennen, het gedrag te analyseren en te bevestigen dat de beveiliging correct werkt. In het artikel hebben we laten zien hoe je TenDI (Tencent) kunt herkennen en waar je instructies vindt om het te koppelen of opnieuw te configureren, zodat je de bescherming met vertrouwen kunt onderhouden en de werking onder controle kunt houden.