web 端怎么通过 UA 中的内容判断客户端是真实用户还是模拟器?

能从访问数据中拿到对方的HTTP请求头的USER-AGENT,有些访问行为异常,但无法判断是否是有问题的,私下问了朋友也没有得到解答,哪位大佬帮忙解答下,怎么从请求头的信息去判断对方是否是真实浏览器还是模拟器;
以下是本次遇到一些行为异常的请求头案例
image.png

阅读 4.7k
1 个回答

没有的,UA 这东西本身就可以随便修改的。

用户在使用浏览器的时候本身也是可以手动改 ua 的。在一些手机端浏览器还可以切换手机端和 PC 端。

一般判断方法会有多种组合。比如说

  1. 频率。根据特征值,计算操作频率。
  2. 根据 UA 版本,去拿去浏览器的兼容性。比如说一个 android 4.x 的系统肯定不支持箭头函数。不支持 .padStart 之类的方法。
  3. 根据事件支持方式。比如说 ontouchstart 肯定不能在 pc 浏览器中支持。

这个东西大概率也不可能开源,如果开源了,人家就专门打个补丁就绕过了


业界的解决办法,一般也不是判断模拟器。基本就是登陆、验证码、频率: 设备指纹有了解的吗,有免费组件可用吗?

当然也有根据行为来判断的。比如说如果你在一些行为上存在异常,也会导致被风控


list = [];
for(var i in window)
    i.indexOf('on') == 0 && list.push(i)
JSON.stringify(list);

count = {};
["onsearch","onappinstalled","onbeforeinstallprompt","onbeforexrselect","onabort","onblur","oncancel","oncanplay","oncanplaythrough","onchange","onclick","onclose","oncontextlost","oncontextmenu","oncontextrestored","oncuechange","ondblclick","ondrag","ondragend","ondragenter","ondragleave","ondragover","ondragstart","ondrop","ondurationchange","onemptied","onended","onerror","onfocus","onformdata","oninput","oninvalid","onkeydown","onkeypress","onkeyup","onload","onloadeddata","onloadedmetadata","onloadstart","onmousedown","onmouseenter","onmouseleave","onmousemove","onmouseout","onmouseover","onmouseup","onmousewheel","onpause","onplay","onplaying","onprogress","onratechange","onreset","onresize","onscroll","onsecuritypolicyviolation","onseeked","onseeking","onselect","onslotchange","onstalled","onsubmit","onsuspend","ontimeupdate","ontoggle","onvolumechange","onwaiting","onwebkitanimationend","onwebkitanimationiteration","onwebkitanimationstart","onwebkittransitionend","onwheel","onauxclick","ongotpointercapture","onlostpointercapture","onpointerdown","onpointermove","onpointerup","onpointercancel","onpointerover","onpointerout","onpointerenter","onpointerleave","onselectstart","onselectionchange","onanimationend","onanimationiteration","onanimationstart","ontransitionrun","ontransitionstart","ontransitionend","ontransitioncancel","onafterprint","onbeforeprint","onbeforeunload","onhashchange","onlanguagechange","onmessage","onmessageerror","onoffline","ononline","onpagehide","onpageshow","onpopstate","onrejectionhandled","onstorage","onunhandledrejection","onunload","ondevicemotion","ondeviceorientation","ondeviceorientationabsolute","onbeforematch","onpointerrawupdate"]
.reduce((s,n)=>((s[n] = s[n]?s[n]+1:1),s),count);

 ["onsearch","onappinstalled","onbeforeinstallprompt","onbeforexrselect","onabort","onblur","oncancel","oncanplay","oncanplaythrough","onchange","onclick","onclose","oncontextlost","oncontextmenu","oncontextrestored","oncuechange","ondblclick","ondrag","ondragend","ondragenter","ondragleave","ondragover","ondragstart","ondrop","ondurationchange","onemptied","onended","onerror","onfocus","onformdata","oninput","oninvalid","onkeydown","onkeypress","onkeyup","onload","onloadeddata","onloadedmetadata","onloadstart","onmousedown","onmouseenter","onmouseleave","onmousemove","onmouseout","onmouseover","onmouseup","onmousewheel","onpause","onplay","onplaying","onprogress","onratechange","onreset","onresize","onscroll","onsecuritypolicyviolation","onseeked","onseeking","onselect","onslotchange","onstalled","onsubmit","onsuspend","ontimeupdate","ontoggle","onvolumechange","onwaiting","onwebkitanimationend","onwebkitanimationiteration","onwebkitanimationstart","onwebkittransitionend","onwheel","onauxclick","ongotpointercapture","onlostpointercapture","onpointerdown","onpointermove","onpointerup","onpointercancel","onpointerover","onpointerout","onpointerenter","onpointerleave","onselectstart","onselectionchange","onanimationend","onanimationiteration","onanimationstart","ontransitionrun","ontransitionstart","ontransitionend","ontransitioncancel","onafterprint","onbeforeprint","onbeforeunload","onhashchange","onlanguagechange","onmessage","onmessageerror","onoffline","ononline","onpagehide","onpageshow","onpopstate","onrejectionhandled","onstorage","onunhandledrejection","onunload","ondevicemotion","ondeviceorientation","ondeviceorientationabsolute","onbeforematch","onorientationchange","onpointerrawupdate","ontouchcancel","ontouchend","ontouchmove","ontouchstart"].reduce((s,n)=>((s[n] = s[n]?s[n]+1:1),s),count);

Object.entries(count).filter(v=>v[1]<2)

我用 chrome 和 chrome 自带的 device toolbar 测试的。缺一个触摸屏的测试例子。

已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏