ShowMeBug 中如何科学的识别用户浏览器?

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"经常有用户在 ShowMeBug 在线面试过程中,使用一些奇怪的浏览器来打开链接进行视频面试,然后出现一些音视频卡顿等问题。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"多次排查后发现产品的音视频功能一但使用了浏览器的 WebRTC 特性,就会对浏览器的要求特别高,如不在正常的浏览器支持范围内,就容易出现问题。所以我们在检测这个问题时,通常有两种方法识别出浏览器的型号和版本。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一种方法:使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"modernizr","attrs":{}}],"attrs":{}},{"type":"text","text":" 来进行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"feature detection","attrs":{}}],"attrs":{}},{"type":"text","text":", 通过探测这些 API 是否存在,来判读是否可以使用 WebRTC,毕竟 WebRTC 是有浏览器 API 组成。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不过,这种方法不够严谨,WebRTC 是一项很新的技术,今年 1 月份才正式成为官方标准,但目前只支持部份浏览器,稳定性也还需要进一步加强。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"The World Wide Web Consortium (W3C) and the Internet Engineering Task Force (IETF) announced today that Web Real-Time Communications (WebRTC), which powers myriad services, is now an official standard, bringing audio and video communications anywhere on the Web.","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"今年 1 月,W3C 和 IETF 宣布,为无数服务提供支持的 WebRTC 现已成为官方标准。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"———— 2021.01.26","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.w3.org/2021/01/pressrelease-webrtc-rec.html","title":"","type":null},"content":[{"type":"text","text":"网络实时通信 (WebRTC) 改变了通信格局;成为万维网联盟 (W3C) 建议书和多个互联网工程任务组 (IETF) 标准","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"显然,feature detection 不符合我们的应用场景,目前不满足我们的需求,所以此方法 pass。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二种方法,也是我们目前采用的,业内比较通用的办法就是检测 User-Agent。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"curl http://202.38.95.46:12001/ -H \"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) HEICORE/49.1.2623.213 Safari/537.36\"\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"User-Agent 是什么","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用户不能直接去互联网上获取信息,需要一个软件作为载体去代表用户的行为,这个软件就是 User-Agent (用户代理),浏览器就是一种典型的 User-Agent 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用户使用不同的软件去用统一的协议去做相同的事情。这也是定义在 http 请求里的,每一条 http 请求一定会携带 User-Agent 头 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"网站的服务者可以通过 User-Agent 头来判断用户使用了什么浏览器,当然也可以根据 User-Agent 的内容来提供差异化的服务。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"标准语法和历史","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原本 User-Agent 浏览器的语法是很清晰的","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"User-Agent: / ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent","title":"","type":null},"content":[{"type":"text","text":"User-Agent - HTTP | MDN","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因为可以根据 User-Agent 的内容来提供差异化的服务,所以当年在浏览器大战时期,浏览器的实现各不相同。当年 Mozilla (Firefox 的前身)浏览器最强的,很多网站都只对 Mozilla 提供高质量的服务,后来有人把自己伪装成了 Mozilla (没错,就是 IE 先开始的)。从此 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Mozilla/5.0","attrs":{}}],"attrs":{}},{"type":"text","text":" 就变成了 User-Agent 的第一段。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://webaim.org/blog/user-agent-string-history/","title":"","type":null},"content":[{"type":"text","text":"History of the browser user-agent string","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"后来的浏览就在这上面不断扩充,就像今天这样:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Linux / Firefox","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Mac OS / Safari","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Safari/605.1.15","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Chromium OS / Chrome","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"Mozilla/5.0 (X11; CrOS x86_64 13904.16.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.25 Safari/537.36","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Windows / Edge","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4482.0 Safari/537.36 Edg/92.0.874.0","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这就变成了去识别 User-Agent 变得很困难,目前的识别基本上都是使用正则表达式,配合自己的 User-Agent 库来判断。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这方面的库有很多,对比很多后,这个库是比较全的 ","attrs":{}},{"type":"link","attrs":{"href":"https://www.npmjs.com/package/ua-parser-js","title":"","type":null},"content":[{"type":"text","text":"ua-parser-js","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"目前几乎所有的网站识别浏览器都是 User-Agent 来判断,有两个接口:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前端有浏览器接口:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"window.navigator.userAgent","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"后端可以通过浏览器的 http request header 来拿到 User-Agent","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如何使用 User-Agent在移动端因为算力的问题,在有些老旧的处理器上也会出现卡顿的情况,不过,我们可以在浏览器里跑一下 Benchmark 来判断算力是否够用,移动端的 User-Agent 会携带处理器信息(可以去查数据库来判断)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以说,目前所进行的操作是:","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"检测用户浏览器 ——> 给予提示,并在文档页显示支持性列表","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最后,要通过定义的规则生成这样一个表格:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/11/1112132c5ccd5d3246c8be19d152806d.png","alt":"browser-list","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"为了降低未来的维护成本要使用一套数据源,既可以检测,又可以在文档页生成列表","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ua-parser-js","attrs":{}}],"attrs":{}},{"type":"text","text":" 的返回结果的数据结构比较科学,直接复用这一数据结构","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"interface Result {\n ua: string;\n browser: {\n name: string | undefined;\n version: string | undefined;\n };\n device: {\n model: string | undefined;\n type: string | undefined;\n vendor: string | undefined;\n };\n engine: {\n name: string | undefined;\n version: string | undefined;\n };\n os: {\n name: string | undefined;\n version: string | undefined;\n };\n cpu: {\n architecture: string | undefined;\n };\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这样我们可以定义三条规则:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"daily_list","attrs":{}}],"attrs":{}},{"type":"text","text":" (某个测试版的浏览器)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"white_list","attrs":{}}],"attrs":{}},{"type":"text","text":" (测试过没有问题的浏览器)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"black_list","attrs":{}}],"attrs":{}},{"type":"text","text":" (已知有问题的浏览器)","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"// 存在优先级关系: daily_list > white_list > black_list\n//\n// https://www.npmjs.com/package/ua-parser-js\n// @params: ua-parser-js.result\n// @params: { : }\n// @return: string(list_name)\nfunction browserDetect(ua, list) {\n const { daily_list, white_list, black_list } = list\n if (checkList(ua, daily_list)) return 'daily_list'\n if (checkList(ua, white_list)) return 'white_list'\n if (checkList(ua, black_list)) return 'black_list'\n return ''\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基于这种数据结构,加入一种简单的语法。支持版本号判断,加入这个几种符号的支持:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":">","attrs":{}}],"attrs":{}},{"type":"text","text":", ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"≥","attrs":{}}],"attrs":{}},{"type":"text","text":", ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"=","attrs":{}}],"attrs":{}},{"type":"text","text":", ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"= 85.0.0.0\"\n - browser:\n name: \"Firefox\"\n version: \">= 85.0.0.0\"\n - browser:\n name: \"Edge\"\n version: \">= 45.0.0.0\"\n device:\n type: \"mobile\"\n os:\n name: \"Android\"\n version: \">= 10.0\"\n\nblack_list:\n # 老版本的 Edge 不支持\n - browser:\n name: \"Edge\"\n version: \"< 80.0.0.0\"\n os:\n name: \"Windows\"\n\n # 手机微信内置浏览器\n - browser:\n name: \"WeChat\"\n device:\n type: \"mobile\"\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用我们产品的用户,上至自己编译浏览器自己用的极客,下至用微信内置浏览器的小白, 所以要在 beta 版、dev 版、canary 开发版、nightly 版等各种版本中给予提示,检测 WebRTC 不稳定,就可能会有问题。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"曾经有人用了开发版的浏览器,面试中出现音视频不稳定,直到他更新了的版本之后才恢复正常。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由于开发版浏览器并不会在 ua 里面携带 dev 的标识,只能通过版本号来判断。可以使用 caniuse-lite 的数据库,取出最新稳定版的的版本号,然后进行版本号比对。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是 caniuse-lite 的数据库有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"1.3M","attrs":{}}],"attrs":{}},{"type":"text","text":" 如果直接使用,会打包整个数据库。这个体积的增加了太多,需要优化一下,所以采用把查询结果打包成文件的办法,实际上真正有用的数据非常的少。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"创建一个生成器,可以动态创建这个文件 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"latest_browser_list_generator.js","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"#!/usr/bin/env node\n\nconst browserslist = require('browserslist')\nconst fs = require('fs')\n\nconst list = {\n 'firefox': true,\n 'chrome': true,\n 'edge': true,\n}\n\nconst latest = browserslist(\"last 1 version\").filter(i => list[i.split(' ')[0]])\nfs.writeFileSync('latest_browser_list.js', `export default ${JSON.stringify(latest)}`)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之后定期执行这两个就可以了","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"npx browserslist@latest --update-db","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"node latest_browser_list_generator.js","attrs":{}}],"attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"当然,这个可以用 GitHub action 或 GitLab CI 来每周执行一次","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"除此之外,360 浏览器的检测方法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"360 浏览器隐藏了自己的 UA 。360 浏览器只有在访问自己的网站(比如:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"360.cn","attrs":{}}],"attrs":{}},{"type":"text","text":")是才会在 UA 里携带 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"QIHU 360SE","attrs":{}}],"attrs":{}},{"type":"text","text":" (360 安全浏览器)或 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"QIHU 360EE","attrs":{}}],"attrs":{}},{"type":"text","text":" (360 极速浏览器)字段","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.v2ex.com/t/425627","title":"","type":null},"content":[{"type":"text","text":"360 安全浏览器和 360 极速浏览器的判断","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"对待国内浏览器(这个可以检测到 360)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://github.com/mumuy/browser","title":"","type":null},"content":[{"type":"text","text":"GitHub - mumuy/browser: Useragent analysis tool.浏览器分析判断工具 - 用户代理、操作系统信息","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不过这个库的作者并没有提供可以直接使用包,只能把核心代码提取出来。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":" // https://github.com/mumuy/browser/blob/4a50ee18cc76a5013dea3596bb33fbab9ed584c3/Browser.js#L111-L143\n if (_window.chrome) {\n let chrome_version = u.replace(/^.*Chrome\\/([\\d]+).*$/, '$1')\n if (_window.chrome.adblock2345 || _window.chrome.common2345) {\n match['2345Explorer'] = true\n } else if (\n _mime('type', 'application/360softmgrplugin') ||\n _mime('type', 'application/mozilla-npqihooquicklogin')\n ) {\n is360 = true\n } else if (chrome_version > 36 && _window.showModalDialog) {\n is360 = true\n } else if (chrome_version > 45) {\n is360 = _mime('type', 'application/vnd.chromium.remoting-viewer')\n if (!is360 && chrome_version >= 69) {\n is360 = _mime('type', 'application/hwepass2001.installepass2001') || _mime('type', 'application/asx')\n }\n }\n }\n\n // 修正\n if (match['Mobile']) {\n match['Mobile'] = !(u.indexOf('iPad') > -1)\n } else if (is360) {\n if (_mime('type', 'application/gameplugin')) {\n match['360SE'] = true\n } else if (\n _navigator &&\n typeof _navigator['connection'] !== 'undefined' &&\n typeof _navigator['connection']['saveData'] == 'undefined'\n ) {\n match['360SE'] = true\n } else {\n match['360EE'] = true\n }\n }\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不过这里要注意:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"navigator.mimeTypes","attrs":{}}],"attrs":{}},{"type":"text","text":" 已经从 Web 标准中移除(也许未来的某天这个方法就没法用了)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://developer.mozilla.org/en-US/docs/Web/API/Navigator/mimeTypes","title":"","type":null},"content":[{"type":"text","text":"Navigator.mimeTypes - Web APIs | MDN","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"判断 360 的版本,是做了一个版本的对应关系","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"// https://github.com/mumuy/browser/blob/4a50ee18cc76a5013dea3596bb33fbab9ed584c3/Browser.js#L283-L292\nfunction get360SEVersion(u) {\n let hash = { '86': '13.0', '78': '12.0', '69': '11.0', '63': '10.0', '55': '9.1', '45': '8.1', '42': '8.0', '31': '7.0', '21': '6.3' }\n let chrome_version = u.replace(/^.*Chrome\\/([\\d]+).*$/, '$1')\n return hash[chrome_version] || ''\n}\nfunction get360EEVersion(u) {\n let hash = { '86': '13.0', '78': '12.0', '69': '11.0', '63': '9.5', '55': '9.0', '50': '8.7', '30': '7.5' }\n let chrome_version = u.replace(/^.*Chrome\\/([\\d]+).*$/, '$1')\n return hash[chrome_version] || ''\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"最后","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"虽然我们分享了如何科学识别检测用户浏览器的方法,但是为了网络环境的健康,为了不重蹈浏览器大战时的覆辙,呼吁大家不要针对特定浏览器提供差异化内容。","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章