V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kisshere
V2EX  ›  程序员

网页上一个按钮的点击,如何用 js 判断为真人点击?

  •  
  •   kisshere · 2022-02-08 09:43:49 +08:00 · 12540 次点击
    这是一个创建于 1017 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我尝试用 js 来追踪鼠标移动的规律来判断,但是移动端没鼠标轨迹咋判断?有没有 PC 和移动端都支持的 js 方法判断真人?
    第 1 条附言  ·  2022-02-08 10:15:56 +08:00
    其实更为准确的说是,js 结合后端一起验证是否为真人点击
    71 条回复    2023-12-12 23:01:36 +08:00
    pathletboy
        1
    pathletboy  
       2022-02-08 09:45:17 +08:00
    能判断就不需要 recaptcha 了
    InDom
        2
    InDom  
       2022-02-08 09:46:00 +08:00
    验证码
    ramcasky
        3
    ramcasky  
       2022-02-08 09:46:18 +08:00
    上验证码
    musi
        4
    musi  
       2022-02-08 09:46:49 +08:00   ❤️ 27
    kisshere
        5
    kisshere  
    OP
       2022-02-08 09:53:36 +08:00
    @pathletboy invisible recaptcha 有使用次数限制
    @InDom
    @ramcasky 验证码太繁琐,就想悄悄验证不影响用户体验
    kop1989smurf
        6
    kop1989smurf  
       2022-02-08 09:55:36 +08:00   ❤️ 1
    如果楼主说的真的成立,那么 reCAPTCHA 是在做什么?
    受限于浏览器的权限限制,反机器人几乎不可能在客户端准确的侦测。
    所以包括 reCAPTCHA 都是通过特征识别+验证码拷问来验证的。
    nba2k9
        7
    nba2k9  
       2022-02-08 09:56:52 +08:00   ❤️ 2
    js 打开电脑摄像头
    kisshere
        8
    kisshere  
    OP
       2022-02-08 09:59:20 +08:00
    @musi 谢谢,这个无头浏览器能模拟出来吗?
    R18
        9
    R18  
       2022-02-08 10:03:48 +08:00
    点击事件中 有一个 event.isTrusted
    h1104350235
        10
    h1104350235  
       2022-02-08 10:03:52 +08:00
    不用 recaptcha 判断真人,如果真的能实现的话,那为什么那么多要用 recaptcha 呢
    你这个需求是个伪命题
    IvanLi127
        11
    IvanLi127  
       2022-02-08 10:06:01 +08:00 via Android
    首先,先实现能判断是否是真人点击的浏览器;然后,弄个 jsbridge ;最后,用 js 调用 api 。
    KyleLrz
        12
    KyleLrz  
       2022-02-08 10:07:34 +08:00
    你是不是对 js 有什么误解
    letitbesqzr
        13
    letitbesqzr  
       2022-02-08 10:11:20 +08:00
    印象中支付宝有很多 h5 页面,有类似风控,不加验证码,但是会在 post 信息中包含“加密后的环境、操作信息”
    R18
        14
    R18  
       2022-02-08 10:11:39 +08:00
    现在有第三代 recaptcha 不需要用户点击按钮,或者验证码 直接可以给出一个评分。

    https://developers.google.com/recaptcha/docs/v3
    InDom
        15
    InDom  
       2022-02-08 10:12:47 +08:00
    别争了,#4 楼已经给了正确答案了,大家退了吧。
    soulzz
        16
    soulzz  
       2022-02-08 10:18:37 +08:00
    伪命题 防不住的
    python Pyauogui+图像识别
    总有办法能绕过你的限制
    photon006
        17
    photon006  
       2022-02-08 10:19:34 +08:00
    单个点击判断不了,puppeteer 可以模拟正常人鼠标点击,不过可以行为分析多个点击判断是否机器,效果嘛取决于算法,会错判。

    最简单还是用图灵测试,比如楼上举例 recaptcha 。
    imkerberos
        18
    imkerberos  
       2022-02-08 10:27:59 +08:00   ❤️ 1
    开个玩笑: 什么是真人?
    musi
        19
    musi  
       2022-02-08 10:30:01 +08:00
    @kisshere #8 是可以的,毕竟 js 是运行在客户端的。真要说的话 js 的执行环境就是不可信的,你怎么能保证在不可信的执行环境里面得到的执行结果是正确的呢?
    eason1874
        20
    eason1874  
       2022-02-08 10:30:12 +08:00
    不能。JS 向 HTTP 后端提交的任何内容都是可以篡改的。设备环境风控靠黑名单( IP 和设备特征),人机风控靠验证码(机器识别不了的),目前别无他法

    #4 说的 Event.isTrusted 的根据是判断操作是否由 JS 代码触发,不管用的,无头浏览器的操作不依赖网页 JS ,isTrusted 会是 true
    eason1874
        21
    eason1874  
       2022-02-08 10:33:20 +08:00
    @musi #19 不可以。Event.isTrusted 根据网页内 dispatchEvent 判断,无头浏览器的操作并不依赖网页事件。不信你试试
    musi
        22
    musi  
       2022-02-08 10:34:26 +08:00
    @eason1874 看清楚我回的问题 “这个无头浏览器能模拟出来吗?” “是可以的”
    Zy143L
        23
    Zy143L  
       2022-02-08 10:34:51 +08:00 via Android
    你能判断了 就没有验证码什么事了
    eason1874
        24
    eason1874  
       2022-02-08 10:36:01 +08:00
    @musi #22 哦,那没事了,我理解错了
    daliusu
        25
    daliusu  
       2022-02-08 10:39:25 +08:00
    @InDom 这个东西有个限制啊,这是浏览器给的,意味着如果有个浏览器是被篡改的第三方浏览器,这个 api 应该是可以随意更改的,它只要给所有的事件里的都改成 true 就可以绕过了
    mekingname
        26
    mekingname  
       2022-02-08 10:39:45 +08:00
    移动端环境不太清楚,但是在网页上,你可以通过 js 来劫持模拟浏览器的 find_element_by_xxx 方法,当爬虫使用 Selenium/Puppeteer/PlayWright 通过 find_element_by_xxx 定位到某个按钮的时候,你就能知道。
    ganbuliao
        27
    ganbuliao  
       2022-02-08 10:41:20 +08:00
    只能通过 recaptcha 获取评分了
    monetto
        28
    monetto  
       2022-02-08 10:43:42 +08:00
    可不可以通过点击位置来进行判断?点击的时候获取点击位置。
    tonywangcn
        29
    tonywangcn  
       2022-02-08 10:58:16 +08:00   ❤️ 4
    Event.isTrusted 并不可靠,puppeteer 即可破防 https://github.com/puppeteer/puppeteer

    `
    Q: What’s the difference between a “trusted" and "untrusted" input event?
    In browsers, input events could be divided into two big groups: trusted vs. untrusted.

    Trusted events: events generated by users interacting with the page, e.g. using a mouse or keyboard.
    Untrusted event: events generated by Web APIs, e.g. document.createEvent or element.click() methods.
    Websites can distinguish between these two groups:

    using an Event.isTrusted event flag
    sniffing for accompanying events. For example, every trusted 'click' event is preceded by 'mousedown' and 'mouseup' events.
    For automation purposes it’s important to generate trusted events. All input events generated with Puppeteer are trusted and fire proper accompanying events. If, for some reason, one needs an untrusted event, it’s always possible to hop into a page context with page.evaluate and generate a fake event:

    await page.evaluate(() => {
    document.querySelector('button[type=submit]').click();
    });

    `
    iColdCat
        30
    iColdCat  
       2022-02-08 11:01:50 +08:00
    @nba2k9 我看刑 很可拷
    allengu2pgyer
        31
    allengu2pgyer  
       2022-02-08 11:03:42 +08:00
    @pathletboy 哈哈哈,真相了
    InDom
        32
    InDom  
       2022-02-08 11:30:12 +08:00
    调用支付宝 /微信支付吧,能付款的就是真人。

    相当于间接使用了 支付宝 微信 的风控识别系统,比自己实现强多了。
    iqoo
        33
    iqoo  
       2022-02-08 11:30:44 +08:00
    @musi 没用的。这种只能识别注入脚本调用 button.click()
    jones2000
        34
    jones2000  
       2022-02-08 13:01:00 +08:00   ❤️ 1
    手机点击的时候判断手指温度, 温度不正常的都是假人。
    makelove
        35
    makelove  
       2022-02-08 13:47:13 +08:00
    用验证码无非是为了防止别人天量 0 成本提交,如果能做到提交效率和对方真人手工操作差不多,那是不是可解了?
    比如提交时要 CPU 挖够半分钟矿(假设真人提交一次要半分钟),这样就限制了对方速度。当然这个也挡不住对方有海量机器。
    Buges
        36
    Buges  
       2022-02-08 13:47:29 +08:00 via Android
    有必要就上验证码。
    其实我担心 invisible recaptcha 普及,导致从“有必要就上”变成“没必要就不去掉”,这样让自动化寸步难行。
    Features
        37
    Features  
       2022-02-08 14:08:55 +08:00
    如果不是很严格的判断是可以的
    谷歌 2007 年就开始的项目,通过键盘敲击,鼠标轨迹,点击频率判断是否为机器人
    如果是机器人就弹出验证码
    所以谷歌验证码在弹出之前,会有个加载动画,是依据之前收集的数据判断机器人,如果数据太少了或者判断为机器人,就会要求输入验证码
    miaomiaoweiwei
        38
    miaomiaoweiwei  
       2022-02-08 14:40:50 +08:00   ❤️ 1
    安全从业来告诉你,这是个伪命题,这压根不是你一个需求能做到的事情,是综合各种行为和结果联合判定的
    这个判定也不是非黑即白的,很多灰色无法判定
    建议看一看人机识别的文章啥的,这就不是一个方法搞定的事情
    RickyC
        39
    RickyC  
       2022-02-08 15:05:59 +08:00
    真人移动鼠标会哆嗦吧
    机器轨迹和人的轨迹,比较一下?
    wangtian2020
        40
    wangtian2020  
       2022-02-08 15:17:35 +08:00
    @RickyC 禁止罗技鼠标开启平滑移动功能是吧?
    CaptainD
        41
    CaptainD  
       2022-02-08 15:18:48 +08:00
    @RickyC 那么有没有可能机器也哆嗦哆嗦
    shijingshijing
        42
    shijingshijing  
       2022-02-08 15:19:45 +08:00
    点一次弹一次 captcha ,再不济点一次弹一次人脸识别,保管行。
    RickyC
        43
    RickyC  
       2022-02-08 16:17:18 +08:00
    @CaptainD 当然有可能。
    但是很多网站的滑块验证,就是检测哆嗦吧。

    机器哆嗦和人通常不同。
    pengtdyd
        44
    pengtdyd  
       2022-02-08 16:21:42 +08:00
    你就没有怀疑你自己的思路错了吗?????????????
    krapnik
        45
    krapnik  
       2022-02-08 17:07:16 +08:00
    isTrusted 无需无头都可以破
    https://note.youdao.com/s/6P2ncGu6
    herozzm
        46
    herozzm  
       2022-02-08 17:38:33 +08:00
    headless 无头 chrome 可以模拟的鼠标移动点击,和真人一样,所以前端 js 只能制造难度,无法真正判别真人
    Maskeney
        47
    Maskeney  
       2022-02-08 18:06:36 +08:00
    @jones2000 #34 你就是提出根据手机壳颜色换壁纸的产品经理是吧
    locoz
        48
    locoz  
       2022-02-08 18:25:22 +08:00
    很简单,使用现成的安全产品...你连相关知识都没有,自己做的校验根本不可能比别人的产品还要好,随便就被破了,形同虚设。
    mostkia
        49
    mostkia  
       2022-02-08 19:10:41 +08:00
    你之前的思路可以考虑的,有一定合理性,至少能排除一部分机器人,因为机器人的高效是跳过了 UI 交互这步骤直接对目标进行访问的,可以在目标按钮被激活时使用 document.msElementsFromPoint 和 mousedown 来配合来查看指针落点是否在按钮上并且按下。当然如果原理被人家搞懂了,估计又会操作鼠标进行模拟操作,本质上不是一个维度的对抗,人家可以调用整个系统 api ,你只能困在浏览器里面,就像囚徒困境那样(任何的反机器人只是增加代码自动化操作的难度)并不是必须要一招鲜吃遍天,可以多种低成本方案结合起来用。
    jones2000
        50
    jones2000  
       2022-02-08 19:53:27 +08:00
    @Maskeney 手机壳颜色换壁纸太 low 了。 开前置摄像头,根据用户衣服更换壁纸。
    neutrinos
        51
    neutrinos  
       2022-02-08 22:17:54 +08:00 via iPhone
    上 honeypot
    rekulas
        52
    rekulas  
       2022-02-08 23:10:51 +08:00
    我觉得在某种意义上是可以的,首先 isTrusted 是足够可信的 @krapnik 提到的方法已经难以伪造事件,所以纯 js 很难直接模拟点击
    其次无论你是基于 selenium 还是 puppeteer 还是其他的 devtools 协议工具,浏览器都会标记一些只读属性,网站可以通过判断这些属性来判断用户是否正在进行作弊
    所以我能想到的唯一破解手段是中间人+浏览器控制,通过中间人篡改网站的判断逻辑,当然这可能需要大量工作量
    特别是网站如果同时引入了 wasm 的话,那无疑相当于一个 app 逆向工程了,一般人难以搞定,基本可以说 99%的情况下可以判断是否真人
    Rocketer
        53
    Rocketer  
       2022-02-08 23:43:18 +08:00   ❤️ 2
    十几年的经验告诉我——技术永远解决不了作弊,只会给正常用户带来痛苦。最终解决问题的只有产品设计,让作弊者不影响自己的正常经营或者无利可图即可。
    dayeye2006199
        54
    dayeye2006199  
       2022-02-09 03:41:59 +08:00
    感觉你们的用户会很痛苦
    xuanbg
        55
    xuanbg  
       2022-02-09 08:29:32 +08:00
    按键精灵点击也不算真人的话,那就没办法了。
    abc8678
        56
    abc8678  
       2022-02-09 08:35:59 +08:00 via Android
    判断鼠标位置? https://b23.tv/av551341157/p1
    kindjeff
        57
    kindjeff  
       2022-02-09 09:01:31 +08:00
    makelove
        58
    makelove  
       2022-02-09 09:08:17 +08:00
    @rekulas 浏览器是开源的,直接找到 isTrusted 函数顶上加一行 return true 不就玩事了
    libook
        59
    libook  
       2022-02-09 10:53:02 +08:00
    前端完全不可信,任何前端的反作弊措施了理论上都是可以被伪造绕过的,就是看针对大多情况是否可以通过分析特征来判断是否大概率是作弊行为,就这还有不低的误判率。

    现在涉及到发短信验证码的基本都强制要求加人机校验了(图形验证码、滑动验证、点击验证等),也就是说没有靠谱的方案可以准确判断作弊行为,一律默认是机器人,做对了验证题才相信是人。
    rekulas
        60
    rekulas  
       2022-02-09 10:54:38 +08:00
    @makelove 是的 我也知道没有办法完全防止 但是
    编译 chrome 已经能难道 90%的技术了
    lneoi
        61
    lneoi  
       2022-02-09 10:58:56 +08:00
    这不就是验证码要做的事情, 不单单是指弹出式主动交互的验证码
    dany813
        62
    dany813  
       2022-02-09 11:34:42 +08:00
    @musi 这个貌似不错啊
    collen
        63
    collen  
       2022-02-09 11:46:28 +08:00
    直接火箭筒把他家炸开 看看是不是真人在操作
    itechnology
        64
    itechnology  
       2022-02-09 11:58:39 +08:00
    这个根本用 js 做不到,不然为什么 12306 会有之前的各种验证图形?
    yangyifan
        65
    yangyifan  
       2022-02-09 12:57:44 +08:00   ❤️ 1
    我觉得这个可以拆分成好几个问题去解决。
    1:检测页面是否是正常用浏览器打开。用于去排除直接发请求、无头、操控浏览器等作弊方式去访问。
    2:收集被点击元素的 xpath 、重力感应等信息、Event.isTrusted 、clientX/Y 、pageX/Y 、mousemove 事件的全部数据, 对称加密加密后发送给后端。用于判断点击时是否是否是作弊行为点击
    3:在落地页检测 referer 、window.performance.timing.type 等信息去判断从页面 a 到落地页面打开的方式是否正常。

    甚至还可以收集浏览器指纹等信息。比如:
    1:指纹信息( canvas 、webgl 、声卡)
    2:判断是否是正常浏览器
    3:电量信息,比如是否在充电、电量剩余百分之多少
    4:检测是否对浏览器原生属性或者方法有修改。比如模拟器上的 navigator.platform 基本上都是非 arm 平台,但是可以通过注入脚本的方式去改变它,所以为了安全,一般还会去检测是否修改了当前属性。
    5:通过 stu 协议检测当前的网络环境是否作弊。

    还有一种是魔改 chromium 的。这类检测其实更多的是通过策略或者流量来源等方式去判断。

    如果对这类问题有想法的欢迎来探讨。wv:dHl1YTA3 ( base64 )
    g5tf87
        66
    g5tf87  
       2022-02-09 15:57:37 +08:00
    @yangyifan

    1:检测页面是否是正常用浏览器打开。用于去排除直接发请求、无头、操控浏览器等作弊方式去访问。

    这一步就很难了,因为现在有很多手段可以做到不同层级的模拟浏览器,比如 nodejs 模拟环境(比直接发请求高级,有 js 执行环境,再加上 jsdom 等技术,几乎是真实浏览器了),pupeteer 修改关键对象 /属性(导致无法判断无头,webdriver 等)
    Stringify
        67
    Stringify  
       2022-02-09 16:58:42 +08:00
    isTrusted + 判断点击位置的 x 、y
    如果是代码 .click() 触发的话,x,y 会是按钮左上角初始位置
    当然这种方式只是防君子而已,但感觉能拦住挺多了
    yangyifan
        68
    yangyifan  
       2022-02-09 17:29:32 +08:00   ❤️ 1
    @g5tf87 不难,而且有现成的思路。
    如果阻止直接发请求的作弊方案,可以增加日志的方式,生成一些加密信息,然后把 js 混淆 就行了,后端把加密信息离线的解密出来,判断这些信息是否都合规。如果混淆逻辑自研是很难解密出来的,如果觉得混淆能解密出来的请尝试解密一下优酷的 tfstk 、l 等加密的 cookie 。

    如果有 js 环境,其实有些浏览器的 api 是很难完全模拟出来的,比如 重力感应、电量、设备的 screen 信息(包含 client offset 、screen 等)至少我知道的反作弊手段如果拿 jsdom 去模拟出来是做不到。就算模拟出来了,还有判断你这些 api 是否是 [native code]。

    如果只有少部分模拟不出来 js 环境,想尝试通过动态修改 js 代码的方式设置值,还可以通过给 js 代码生成 hash 值的方式判断有没有动态修改了 js 。

    总而言之,从我的反作弊经验来说这些基本上都能防范到。当然,不排除有大神把这些都能解决掉。
    mestrace
        69
    mestrace  
       2022-02-11 15:22:40 +08:00
    可以了解下 device finger-printing 。理论上通过浏览器的一些原信息,就能以较高的置信度判断你是在什么环境里了。理论上无头浏览器都可以检测出来的。可以看下 amiunique 。org ,这个网站能显示你当前的 dfp 。各家肯定都有类似的算法去检测设备。
    另外就是 recaptcha 让用户填验证码,根据行为来判断是否为机器。
    g5tf87
        70
    g5tf87  
       2022-02-14 14:43:22 +08:00
    @yangyifan
    是的。 你这个思路已经是商用版本了👍
    目前市面上的常用反作弊产品都差不多如此实现
    will800
        71
    will800  
       345 天前
    @yangyifan 这样的大神估计头上只剩下 3 根毛了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   971 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 20:57 · PVG 04:57 · LAX 12:57 · JFK 15:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.