在本文中,我们尽量回答了所有关键问题。要开始解决问题,第一步是确定当前使用的是哪种防护系统。为此,您可以查看常见验证码与反机器人防护系统列表,其中提供了可视化示例和关键特征,帮助您快速判断自己正在使用哪一种方案。
如果您发现自己的网站使用的是 TenDI (Tencent),下一步就是更深入地了解它的特性和具体工作方式。在本文中,您还可以查看 TenDI (Tencent) 的接入说明,以便彻底弄清它在您的网站上是如何运行的。这样一来,您不仅能更好地理解当前的防护机制,还可以更合理地规划后续的维护和支持。
通过 CapMonster Cloud API 工作的一般流程:
type - CustomTask
class - TenDI
websiteURL - 验证码所在页面的 URL。
websiteKey - captchaAppId。例如 "websiteKey": "189123456" — 您网站的唯一参数
captchaUrl (metadata 内) - 验证码脚本链接,通常以 TCaptcha.js 或 TCaptcha-global.js 结尾;
websiteURL - 验证码所在页面地址;
userAgent(可选) - 浏览器 User-Agent。请仅提供最新 UA,来自 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';
// 替换为自己的值
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. 打开页面
await page.goto(WEBSITE_URL, { waitUntil: 'networkidle' });
// 2. 等待 CAPTCHA 出现(如 input 或 iframe)
await page.waitForSelector('#tendi_response, iframe[src*="tendi"], input[name="tendi_response"]', { timeout: 15000 });
// 如有需要,可从页面提取 websiteKey
const WEBSITE_KEY = await page.evaluate(() => {
// 示例:sitekey 可能在 data 属性或全局变量中
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. 创建 TenDI 任务
const tenDIRequest = new TenDIRequest({
websiteURL: page.url(),
websiteKey: WEBSITE_KEY,
});
const balance = await client.getBalance();
console.log("Balance:", balance);
// 4. 解决验证码
const solution = await client.Solve(tenDIRequest);
console.log("Solution:", solution);
const { ticket, randstr } = solution.solution.data;
// 5. 插入解决结果的方法
await page.evaluate(({ ticket, randstr }) => {
// 插入 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 回调函数
if (typeof window.onCaptchaSolved === 'function') {
window.onCaptchaSolved(ticket, randstr);
inserted = true;
}
// 若无 input 和 callback
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);
将获得两个参数:CaptchaAppId 和 AppSecretKey,用于前端和服务器。
点击出现 CAPTCHA,完成后结果显示在控制台。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Captcha Example</title>
// 必须加载 CAPTCHA JS
<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>
// 处理结果
function callback(res) {
console.log("callback:", res);
if (res.ret === 0) {
// 验证成功
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 和 randstr 已复制到剪贴板。");
}
}
// 处理 CAPTCHA 脚本加载错误
function loadErrorCallback() {
const appid = "CaptchaAppId";
const ticket = `trerror_1001_${appid}_1769260382`;
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>
集成工作原理
步骤 1: 加载 CAPTCHA JS
脚本需动态加载:
<script src="https://ca.turing.captcha.qcloud.com/TJNCaptcha-global.js"></script>非标准加载或缓存可能导致 CAPTCHA 运行不正常。
步骤 2: 创建 TencentCaptcha 对象
加载 JS 后出现全局类:
<script src="new TencentCaptcha(domElement, CaptchaAppId, callback, options);"></script>参数:
domElement - 嵌入 checkbox/iframe 的容器
CaptchaAppId - 您的 ID
callback - 验证完成后的操作
options - 外观设置(可选)
步骤 3: 调用方法 .show()
captcha.show();显示 CAPTCHA,可多次调用。
步骤 4: 处理结果
Callback 接收对象:
{
ret: 0, // 0 -- 成功, 2 -- 用户关闭窗口
ticket: "...", // 服务器需要
randstr: "...", // 服务器也需要
errorCode: 1001, // 如果 CAPTCHA 未加载
errorMessage: "..." // 错误文本
}服务器必须进行二次 ticket 验证。
"灾难恢复模式"
若 CAPTCHA 未加载(如 CDN 不可用),可自动发放“紧急票”,不影响业务流程。
场景:
trerror_<errorcode>_<appid>_<timestamp>AppId 加密(可选)
如需最高安全,可发送加密版本 AppId,而非明文:
aidEncrypted = Base64(IV + AES256(AppId & timestamp & ttl))需要:
服务器端加密示例 (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")服务器验证
步骤 1. 配置 API 访问
在密钥管理面板 (CAM / API Key Management) 获取 API 的 SecretId 和 SecretKey,用于签名请求。
步骤 2. 调用 API DescribeCaptchaResult
客户端返回 ticket 和 randstr 后,服务器发送请求:
参数:
CaptchaType - 9 (固定值)
Ticket - 字符串 — 客户端返回的 ticket
Randstr - 字符串 — 客户端返回的 randstr
CaptchaAppId - 您的 AppId
AppSecretKey - 您的密钥
UserIp - 用户 IP(建议提供)
步骤 3. 处理响应
API 返回:
如果 CaptchaCode === OK,用户视为通过验证,否则拒绝。
示例 — Node.js 验证 ticket
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", // 如果需要,指定地区
});
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;
}关于将 Tencent CAPTCHA 集成到网站的更多信息,请参考 官方文档。
如果你接手了一个已经集成了验证码或其他防护系统的网站,但又无法访问其代码,也不用担心!要判断实际使用了哪种技术其实并不难。为了核实其是否正常工作,你可以在隔离的测试环境中使用CapMonster Cloud识别服务,确保令牌处理机制和校验逻辑都运行正常。
对于TenDI (Tencent),只需识别出所用的系统,观察其行为,并确认防护是否正常工作即可。本文演示了如何识别 TenDI (Tencent),以及到哪里查找其接入或重新配置的说明文档,从而帮助你自信地维护防护方案并掌控其运行情况。