[ PROMPT_NODE_24396 ]
常见问题与注意事项
[ SKILL_DOCUMENTATION ]
# 故障排查与注意事项
## 关键规则
### ❌ 跳过服务端验证
**问题:** 仅客户端验证极易被绕过。
**解决方案:** 务必在服务端进行验证。
javascript
// 正确 - 服务端验证 token
app.post('/submit', async (req, res) => {
const token = req.body['cf-turnstile-response'];
const validation = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
method: 'POST',
body: JSON.stringify({ secret: SECRET, response: token })
}).then(r => r.json());
if (!validation.success) return res.status(403).json({ error: 'CAPTCHA 验证失败' });
});
### ❌ 泄露密钥 (Secret Key)
**问题:** 密钥在客户端代码中泄露。
**解决方案:** 仅限服务端验证。切勿将密钥发送到客户端。
### ❌ 重复使用 Token (一次性规则)
**问题:** Token 是一次性的。重复验证会失败并返回 `timeout-or-duplicate`。
**解决方案:** 每次提交生成新 Token。出错时重置小部件。
javascript
if (!response.ok) window.turnstile.reset(widgetId);
### ❌ 未处理 Token 过期
**问题:** Token 5 分钟后过期。
**解决方案:** 处理过期回调或使用自动刷新。
javascript
window.turnstile.render('#container', {
sitekey: 'YOUR_SITE_KEY',
'refresh-expired': 'auto', // 或使用 'manual' 配合 expired-callback
'expired-callback': () => window.turnstile.reset(widgetId)
});
## 常见错误
| 错误 | 原因 | 解决方案 |
|-------|-------|----------|
| **小部件未渲染** | sitekey 错误、CSP 拦截、file:// 协议 | 检查 sitekey,为 challenges.cloudflare.com 添加 CSP,使用 http:// |
| **timeout-or-duplicate** | Token 过期 (>5分钟) 或重复使用 | 生成新 Token,不要缓存超过 5 分钟 |
| **invalid-input-secret** | 密钥错误 | 从仪表板验证密钥,检查环境变量 |
| **missing-input-response** | 未发送 Token | 检查表单字段名是否为 'cf-turnstile-response' |
## 框架注意事项
### React: 小部件重新挂载
**问题:** 状态变更导致小部件重新渲染,丢失 Token。
**解决方案:** 使用 useRef 控制生命周期。
tsx
function TurnstileWidget({ onToken }) {
const containerRef = useRef(null);
const widgetIdRef = useRef(null);
useEffect(() => {
if (containerRef.current && !widgetIdRef.current) {
widgetIdRef.current = window.turnstile.render(containerRef.current, {
sitekey: 'YOUR_SITE_KEY',
callback: onToken
});
}
return () => {
if (widgetIdRef.current) {