You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Web端点击类游戏如何防范自动点击器插件作弊

点击类项目防自动点击作弊可行方案

前端侧基础校验(提高作弊门槛)

  • 事件真实性校验:浏览器原生用户触发的事件isTrusted属性为true,脚本模拟触发的事件该值为false,可作为基础过滤规则。同时要校验事件流顺序:真实用户点击会按pointerdown -> mousedown -> pointerup -> mouseup -> click的顺序触发,各事件间存在合理时间差,直接触发click、跳过前置事件的请求直接判定为异常。
  • 点击频率与间隔校验:人类连续点击的手速上限约为每秒7-9次,持续点击时平均速度会更低,可设置每秒8次的软阈值,超过阈值的点击不计分。同时统计连续点击的时间间隔方差:自动点击器通常为固定间隔触发,间隔方差极小(连续10次点击间隔差小于10ms基本可以判定为脚本),人手点击的间隔波动至少在几十毫秒级别,方差会明显更高。
  • 点击坐标与轨迹校验:自动点击器大多点击固定坐标,真实用户点击同一按钮时,坐标会在按钮范围内存在像素级偏移,若连续5次以上点击坐标完全无偏移可判定为异常。同时可监听鼠标移动事件,若点击前从未触发过按钮区域内的鼠标移动、鼠标直接“瞬移”到按钮位置触发点击,也属于高风险特征。
  • 核心逻辑防护:不要把计分变量暴露在全局作用域(你当前代码中的counter是全局变量,用户打开控制台直接赋值即可篡改分数),将计分、校验逻辑放在闭包中避免外部直接修改,同时可对核心JS代码做混淆,增加用户篡改前端逻辑的成本。

交互层轻量校验(低体验影响)

  • 随机微干扰:每隔几秒将点击按钮的位置随机偏移3-5个像素,或不定期在按钮范围内弹出需要点击的微小校验点,自动点击器按固定坐标点击会点空,无法通过校验。注意不要加入复杂验证码,避免影响正常用户体验。
  • 设备特征校验:移动端场景下可读取触控事件的接触面积、按压力度参数,自动点击器的这类参数通常为0或固定值,真实触控的参数会存在自然波动。

服务端兜底校验(核心防刷手段)

所有前端校验都存在被绕过的可能,只有服务端校验才能从根本上控制作弊风险

  • 点击频率硬上限:给每个用户设置合理的单位时间点击上限,比如每分钟最多300次点击,超过上限的请求直接丢弃,就算前端逻辑被篡改,也无法实现短时间内大量刷分。
  • 行为序列校验:前端不要每次点击都上报“加1分”的请求,而是攒一批点击的原始数据(时间戳、坐标、事件参数)批量上报,服务端复跑前端的特征校验规则,发现异常序列直接不计分,触发高风险规则的账号可加入风控名单。
  • 增长曲线校验:真实用户的分数增长为带波动的线性曲线,中间会存在停顿、休息的间隔,若账号出现短时间分数暴涨、连续数小时无间断点击等不符合人类行为的增长特征,直接标记为异常,可做分数清零或限制操作处理。
  • 操作强校验:所有分数消耗、兑换类操作必须经过服务端校验,以服务端存储的用户分数为准,前端展示的分数仅做参考,避免用户篡改前端参数直接兑换奖励。

针对你当前代码的基础改造示例

以下代码加入了基础的前端防作弊逻辑,将计分变量放在闭包中避免全局篡改,加入了事件真实性、频率、间隔、坐标校验:

@import url('https://fonts.googleapis.com/css2?family=Montserrat&display=swap');

body{
    background: linear-gradient(to right, #11998e, #38ef7d)
}

#title{
    text-align: center;
    font-family: 'Montserrat';
    font-size: 48px;
    font-weight: bold;
    user-select: none;
    margin-top: 2%;
}

#button{
    margin: auto;
    width: 50%;
    height: auto;
    padding: 15px;
    text-align: center;
    border: 3px solid white;
    border-radius: 50px;
    font-family: 'Montserrat';
    font-size: 32px;
    font-weight: bold;
    user-select: none;
    transition-duration: 0.1s;
}

#button:hover{
    cursor: pointer;
    transition-duration: 0.1s;
    background-color: white;
}

#button:active{
    transition-duration: 0.1s;
    transform: scale(0.9);
}
<!DOCTYPE html>
<html>
    <head>
        <title>This is just test</title>
        <link rel="stylesheet" href="clicker.css">
    </head>
    <body>
        <p id="title">Clicker Test</p>
        <div id="button">
            <span id="text">Score:</span>
            <span id="score">0</span>
        </div>
        <script>
            (() => {
                let counter = 0;
                const clickRecords = [];
                // 人类每秒点击上限
                const MAX_CLICK_PER_SEC = 8;
                const button = document.getElementById('button');
                const scoreEl = document.getElementById('score');
                let validMouseDown = false;

                // 点击合法性校验
                const isClickValid = (e) => {
                    if (!e.isTrusted) return false;
                    const now = Date.now();
                    // 清理1秒前的记录
                    while(clickRecords.length && clickRecords[0].time < now - 1000) {
                        clickRecords.shift();
                    }
                    // 频率校验
                    if (clickRecords.length >= MAX_CLICK_PER_SEC) return false;
                    // 间隔方差校验
                    if (clickRecords.length >= 10) {
                        const intervals = [];
                        for(let i = 1; i < 10; i++) {
                            intervals.push(clickRecords[i].time - clickRecords[i-1].time);
                        }
                        const avgInterval = intervals.reduce((a,b) => a+b, 0) / intervals.length;
                        const variance = intervals.reduce((a,b) => a + Math.pow(b - avgInterval, 2), 0) / intervals.length;
                        if (variance < 20) return false;
                    }
                    // 坐标重复校验
                    const last5Clicks = clickRecords.slice(-5);
                    if (last5Clicks.length === 5 && last5Clicks.every(r => r.x === e.clientX && r.y === e.clientY)) {
                        return false;
                    }
                    clickRecords.push({time: now, x: e.clientX, y: e.clientY});
                    return true;
                }

                // 校验完整事件流
                button.addEventListener('mousedown', e => {
                    if (e.isTrusted) validMouseDown = true;
                })
                button.addEventListener('mouseup', e => {
                    if (e.isTrusted) validMouseDown = false;
                })
                button.addEventListener('click', e => {
                    if (!validMouseDown || !isClickValid(e)) return;
                    // 原有点击交互逻辑
                    button.style.width = '45%';
                    setTimeout(() => button.style.width = '50%', 50);
                    counter += 1;
                    scoreEl.innerText = counter;
                    // 此处可添加批量上报逻辑,将clickRecords定期发送到服务端校验
                })
            })()
        </script>
    </body>
</html>

注:没有任何方案能100%阻止刻意作弊的用户,多层校验的核心目标是把作弊成本提高到远大于作弊收益的程度,结合服务端兜底即可覆盖绝大多数作弊场景。


内容的提问来源于stack exchange,提问作者Fieryfeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 10:51:34