INTEGRATION GUIDE
把一次验证接入你的站点
每个业务站点拥有独立的 siteKey 和绑定域名。服务端结合会话状态、一次性凭证与风险策略保护关键流程;成功响应只返回短时 verification ticket。管理后台还提供实时运行状态、授权、审计和风险事件视图。
01 / QUICK START
快速开始
在管理后台新增站点并绑定业务域名。创建成功后立即保存一次性显示的 app_secret,并把可公开的 site_key 配置到前端和业务后端。
浏览器环境变量:TRUSTTURN_SITE_KEY=sl_your_site_key 业务后端环境变量:TRUSTTURN_SITE_KEY=sl_your_site_key 业务后端密钥:TRUSTTURN_APP_SECRET=<只显示一次的 app_secret>
site_key 只用于标识站点,可以公开;app_secret 是业务后端凭证,不能进入浏览器、客户端包、日志或版本库。02 / SDK RENDER
动态创建 iframe 嵌入 TRUSTTURN UI
对接方提供一个容器并由 JavaScript 动态创建组件。这样可以先绑定验证事件,再加载 iframe,并统一处理站点配置和加载状态。
<div id="trustturn-box"></div>
<script>
const apiOrigin = 'https://api.trustturn.cc';
const siteKey = 'sl_portal_8f1a4c2d';
const mount = document.querySelector('#trustturn-box');
window.addEventListener('message', event => {
if (event.origin !== apiOrigin) return;
if (event.data?.type === 'trustturn:verified') {
const ticket = event.data.detail?.verificationTicket;
// 将 ticket 交给你的业务后端
}
});
const frame = document.createElement('iframe');
frame.src = apiOrigin + '/widget.html?site_key=' + encodeURIComponent(siteKey)
+ '&action=' + encodeURIComponent('login');
frame.title = 'TRUSTTURN 人机验证';
frame.style.cssText = 'width:100%;min-height:88px;border:0';
mount.appendChild(frame);
</script>
组件只能从该 siteKey 已绑定的业务域名加载。验证完成后,组件会向父页面发送 trustturn:verified 消息,消息来源必须严格校验为 https://api.trustturn.cc。
window.addEventListener('message', event => {
if (event.origin !== 'https://api.trustturn.cc') return;
if (event.data?.type === 'trustturn:verified') {
const ticket = event.data.detail?.verificationTicket;
// 将 ticket 交给你的业务后端
}
});
03 / SERVER VERIFY
业务后端检查并消费 ticket
新增站点时,服务端会随机生成可公开的 site_key 和只展示一次的 app_secret。浏览器把 ticket 提交给你的业务后端后,由业务后端动态生成时间戳、nonce 和签名,再调用:
curl https://api.trustturn.cc/api/tickets/consume \
-H 'Content-Type: application/json' \
-H 'X-TrustTurn-Timestamp: <13 位 Unix 毫秒>' \
-H 'X-TrustTurn-Nonce: <随机 nonce>' \
-H 'X-TrustTurn-Signature: v1=<HMAC-SHA256 签名>' \
-d '{
"site_key": "sl_your_site_key",
"ticket": "<浏览器提交的 ticket>",
"expected_action": "login"
}'
// 成功响应
{
"success": true,
"site_id": "mailroom",
"site_key": "sl_your_site_key",
"action": "login",
"origin": "https://mail.example.com",
"hostname": "mail.example.com",
"challenge_ts": "2026-10-19T03:00:00.000Z",
"consumed_at": "2026-10-19T03:00:08.000Z",
"risk": { "decision": "allow", "score": 0 }
}
只有 success === true、site_key、action 和 origin 都与当前业务请求一致时才能继续。ticket 默认 60 秒有效,成功响应时立即消费;重复调用会返回 invalid_ticket。
签名规范串依次为协议域、方法、路径、时间戳、nonce、原始请求体摘要,每个字段用换行连接:
TRUSTTURN-TICKET-CONSUME-V1 POST /api/tickets/consume <timestamp> <nonce> SHA256(<原始 JSON 请求体字节>) sign = HMAC-SHA256(app_secret, 上述规范串)
SHA-256 摘要只是绑定原始请求体的公开校验值,不是密码、密钥或加密;真正的请求认证由站点专属 app_secret 计算的 HMAC-SHA256 完成。服务端只接受当前时间前后 2 分钟内的请求,同一站点的 nonce 只能认证一次。签名值不能用于推导 app_secret,修改 ticket、动作或站点都会导致签名失效。ticket 是 64 个以上 Base64URL 字符的随机一次性值,默认 60 秒有效并在成功消费后立即失效。
site_key 可以进入浏览器。app_secret、sign、timestamp 和 nonce 都只能在业务后端生成或保存,禁止放进 HTML、Vue/React 源码、移动端包或返回给浏览器。密钥轮换后旧密钥立即失效。04 / BUSINESS LOGIN
业务登录接口中的正确顺序
// 浏览器 -> 你的业务后端
POST /auth/login
{ "email": "user@example.com", "password": "...",
"verification_ticket": "<ticket>", "site_key": "sl_your_site_key" }
// 你的业务后端:先签名并消费 ticket,再检查密码并创建业务会话
import crypto from 'node:crypto';
const consumeBody = JSON.stringify({
site_key: process.env.TRUSTTURN_SITE_KEY,
ticket: body.verification_ticket,
expected_action: 'login'
});
const timestamp = String(Date.now());
const nonce = crypto.randomBytes(18).toString('base64url');
const bodyHash = crypto.createHash('sha256').update(consumeBody).digest('hex');
const canonical = ['TRUSTTURN-TICKET-CONSUME-V1', 'POST',
'/api/tickets/consume', timestamp, nonce, bodyHash].join('\n');
const sign = crypto.createHmac('sha256', process.env.TRUSTTURN_APP_SECRET)
.update(canonical).digest('hex');
const result = await fetch('https://api.trustturn.cc/api/tickets/consume', {
method: 'POST',
headers: {
'content-type': 'application/json',
'x-trustturn-timestamp': timestamp,
'x-trustturn-nonce': nonce,
'x-trustturn-signature': `v1=${sign}`
},
body: consumeBody
}).then(response => response.json());
if (result.success !== true
|| result.site_key !== process.env.TRUSTTURN_SITE_KEY
|| result.action !== 'login'
|| result.origin !== 'https://mail.example.com') {
throw new Error('验证码无效');
}
/api/login 是 TrustTurn 自带演示账号的登录接口,不是第三方业务后端的 ticket 校验接口。Mailroom 等独立系统必须使用 /api/tickets/consume。
05 / OPERATIONS
错误码与运行边界
invalid_request_signature:签名错误、时间戳超窗、nonce 格式错误或站点尚未配置 app_secret。replayed_request:同一站点的请求 nonce 已使用。invalid_ticket:ticket 不存在、已过期、已消费或属于其他站点。action_mismatch:ticket 的业务动作与expected_action不一致。challenge_binding:验证凭证与当前站点不一致。replayed_token:一次性 challenge 凭证已使用。expired_token:验证超时,组件会自动重新初始化。site_domain_not_allowed:当前域名未绑定到该站点。site_authorization_expired:站点业务授权已到期。site_authorization_frozen:站点业务授权已冻结。site_authorization_revoked:站点业务授权已吊销。session_binding:当前会话环境发生变化。environment_risk:当前访问环境未通过风险校验。
管理员可以在后台配置站点域名、授权范围和风险策略,并查看验证事件。正式部署前请配置管理员强认证、访问审计、数据保留周期与适用的告知机制。