传统 Bot 管理经常围绕单次请求做判断:检查 IP、请求头、速率或某个挑战是否通过。Precursor 引入了另一种观察尺度,把客户端在完整用户旅程中的持续行为汇总为会话级检测信号,用来识别更高级的自动化,同时减少对正常用户的打扰。
从单点判断转向完整会话
单个 HTTP 请求提供的上下文很有限。一个自动化客户端可以模仿浏览器请求头、控制访问频率,甚至执行 JavaScript。如果防护系统只观察登录或提交订单的瞬间,真人和自动化程序可能表现得非常相似。
持续行为验证关注的是一段会话如何展开。例如,系统可以分析页面状态变化、交互事件的时间分布、导航顺序以及前后动作是否一致。来源摘要没有披露 Precursor 使用的具体特征或评分算法,因此不能把任何一项客户端事件视为其官方实现;关键变化在于,检测输入从孤立请求扩展成了会话级行为。
这种视角特别适合发现具备代理式行为的高级自动化。它们可能正确完成每一步操作,却在完整流程中留下不自然的节奏、状态转换或交互组合。会话级分析能够把这些弱信号放到一起,而不是依赖某个容易被绕过的规则。
检测结果不应只有“放行或封禁”
持续信号的价值不仅是提高识别精度,也在于支持更细的处置策略。工程上可以把风险响应设计成阶梯:
- 低风险会话直接放行,不展示挑战。
- 中风险会话增加服务端校验、降低操作速率或要求二次确认。
- 高风险会话触发挑战、限制敏感动作,必要时阻断。
- 信号不足时继续观察,避免因为一次异常交互误伤用户。
这与减少正常用户摩擦的目标一致。系统不必让每位访客都证明自己是人,而是把成本集中到风险较高的会话上。
风险评分还应与业务动作绑定。同一个会话访问公开商品页和批量领取优惠券,容忍度显然不同。检测引擎负责提供行为风险信号,业务服务则结合账户状态、动作价值和历史记录做最终决策。
可以这样实践:构造最小会话信号管道
下面是一个教学性质的最小示例,不代表 Precursor 的官方 API、字段或算法。它演示浏览器如何定期发送聚合计数,以及服务端如何按会话保存信号并返回分级决策。示例刻意不采集按键内容和精确指针轨迹。
安装并启动服务端:
python -m venv .venv
. .venv/bin/activate
pip install fastapi 'uvicorn[standard]'
uvicorn app:app --reload --port 8000
创建 app.py:
from collections import defaultdict
from typing import Literal
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
sessions: dict[str, list[dict]] = defaultdict(list)
class SignalBatch(BaseModel):
session_id: str = Field(min_length=8, max_length=128)
elapsed_ms: int = Field(ge=0)
pointer_events: int = Field(ge=0)
key_events: int = Field(ge=0)
visibility_changes: int = Field(ge=0)
sensitive_action: bool = False
class Decision(BaseModel):
risk: int
action: Literal['allow', 'observe', 'challenge']
@app.post('/signals', response_model=Decision)
def receive_signals(batch: SignalBatch) -> Decision:
sessions[batch.session_id].append(batch.model_dump())
# 仅用于演示数据流,不是生产级 Bot 检测模型。
risk = 0
if batch.sensitive_action and batch.elapsed_ms < 1500:
risk += 55
if batch.sensitive_action and batch.pointer_events == 0 and batch.key_events == 0:
risk += 35
if batch.visibility_changes > 20:
risk += 15
risk = min(risk, 100)
action = 'challenge' if risk >= 70 else 'observe' if risk >= 35 else 'allow'
return Decision(risk=risk, action=action)
在需要保护的页面中加入以下脚本。运行前,把 API_URL 改成实际采集端点,并确保服务端正确配置 CORS、TLS、认证和限流:
<script>
const API_URL = 'http://localhost:8000/signals';
const startedAt = performance.now();
const sessionId = crypto.randomUUID();
const counters = {
pointer_events: 0,
key_events: 0,
visibility_changes: 0
};
window.addEventListener('pointerdown', () => counters.pointer_events++);
window.addEventListener('keydown', () => counters.key_events++);
document.addEventListener('visibilitychange', () => counters.visibility_changes++);
async function reportSignals(sensitiveAction = false) {
const payload = {
session_id: sessionId,
elapsed_ms: Math.round(performance.now() - startedAt),
...counters,
sensitive_action: sensitiveAction
};
const response = await fetch(API_URL, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(payload),
keepalive: true
});
if (!response.ok) throw new Error(`signal API returned ${response.status}`);
return response.json();
}
// 在登录、注册、结算等敏感动作发生前调用。
async function beforeSensitiveAction() {
const decision = await reportSignals(true);
if (decision.action === 'challenge') {
console.log('Show an appropriate verification step');
return false;
}
return true;
}
setInterval(() => reportSignals(false).catch(console.error), 5000);
</script>
真实系统不能直接把“没有鼠标事件”等同于机器人。键盘用户、辅助技术、移动设备、网络延迟和后台标签页都会形成不同的行为模式。示例中的规则只用于说明数据流,生产环境需要经过标注数据验证、设备分群、阈值校准和持续监控。
上线前需要守住的边界
客户端信号可能被伪造,因此服务端必须验证数据结构、限制上报频率,并把行为信号与服务端掌握的请求、账户和事务上下文结合起来。检测逻辑也不应完整下发到浏览器,否则攻击者更容易针对规则优化自动化程序。
隐私边界同样重要。优先采集聚合计数和时间信息,避免记录按键内容、表单值或不必要的精确轨迹;设置较短的数据保留周期,并让采集目的、访问权限和删除流程可审计。还要建立误报指标,按设备类型、地区、无障碍使用场景和关键业务漏斗观察影响。
采用持续行为验证时,可以按以下顺序推进:先在只观察模式下生成风险信号,再与已确认的欺诈和正常会话对照;随后只对高价值动作启用阶梯式响应;确认误报率、挑战率和转化率处于可接受范围后,再逐步扩大覆盖面。Precursor 所代表的方向并不是增加更多无差别挑战,而是利用完整会话中的连续证据,把验证放到真正需要的位置。