用户代理检测
前面的文章介绍的是如何检测浏览器对某一功能的支持情况
但是在实践中我们有些时候免不了需要知道用户到底是用的什么浏览器对我们的站点进行访问
这也是统计用户行为的一部分
用户代理检测这种方式就是用于检测用户访问所使用的浏览器的
那么如何进行检测呢?
我之前的文章,讲JS的navigator对象的时候,其中有个 userAgent 属性
这个属性在每次http请求中都会携带在请求头中,这也是我们常说的用户代理字符串
但是要注意的是,这种客户端检测的优先级应该排在 怪癖检测、能力检测之后
作为一种万不得已的手段
为什么呢?因为这和 电子欺骗 有关
所谓电子欺骗,就是指浏览器通过在用户代理字符串中加入错误、误导信息来影响服务器对用户的判断
为什么浏览器要这样做呢?
这就和web早期的发展有关,在早期的发展过程中,用户代理字符串一开始是统一的
但是到了IE4微软希望占据更大的市场,并且希望体现IE的独立性,所以用户代理字符串中就出现了IE自己的标识
这样做使当时的 Netscape(当时最受欢迎的浏览器)很不爽,所以其合作公司通过在服务端检测用户代理字符串,来区分用户
以此来拒绝IE用户的访问
而IE当然不肯善罢甘休,所以就在用户代理字符串中,在不违反标准的情况下添加了混淆信息
其它浏览器厂商纷纷效仿IE
所以检测用户代理字符串来判断浏览器存在一定的风险,准确性也不高
这种方法也就成为了客户端检测的备选方法
和之前一样,这里还是给出一段检测代码
PS:书中检测的只检测到IE11,然而edge的部分并没有,所以这一部分是我自己测试的,有可能会有些问题
用户代理字符串检测函数
// 无需参数 // 返回一个包含浏览器信息的对象 function getClient() { var engine = { // 保存浏览器引擎 ie: 0, gecko: 0, webkit: 0, khtml: 0, opera: 0, ver: null // 具体版本 }; var browser = { // 浏览器 ie: 0, firefox: 0, safari: 0, konqueror: 0,// 夸克 opera: 0, chrome: 0, ver: null // 浏览器版本 }; var system = { // PC 端 win: false, mac: false, xll: false, // linux // 移动设备 iphone: false, ipod: false, ipad: false, ios: false, android: false, nokiaN: false, winMobile: false, // 游戏平台 wii: false,// 任天堂 ps: false }; var ua = navigator.userAgent;// 获取用户代理字符串 // 浏览器及引擎检测 if(window.opera){// opera 识别 engine.ver = browser.ver = window.opera.version(); engine.opera = browser.opera = parseFloat(engine.ver); }else if(/AppleWebKit/(S+)/.test(ua)){ engine.ver = RegExp["$1"]; // 获取最近一次正则匹配的字符串 engine.webkit = parseFloat(engine.ver); // 判断谷歌和safari if(/Edge/(S+)/.test(ua)){// Edge 伪装的很好 所以先检测 engine.ver = browser.ver = RegExp["$1"]; engine.webkit = 0; engine.ie = "Edge"; browser.ie = "Edge"; }else if (/Chrome/(S+)/.test(ua)){ browser.ver = RegExp["$1"]; browser.chrome = parseFloat(browser.ver); }else if(/Version/(S+)/.test(ua)){ browser.ver = RegExp["$1"]; browser.safari = parseFloat(browser.ver); }else{ // 近似判断低版本 var safariVersion = 1; if(engine.webkit<100){ safariVersion = 1; }else if(engine.webkit<312){ safariVersion = 1.2; }else if(engine.webkit<412){ safariVersion = 1.3; }else{ safariVersion = 2; } browser.safari = browser.ver = safariVersion; } }else if(/KHTML/(S+)/.test(ua) || /Konqueror/([^;]+)/.test(ua)){ // 识别夸克 engine.ver = browser.ver = RegExp["$1"]; engine.khtml = browser.konqueror = parseFloat(engine.ver); }else if(/rv:([^)]+)) Gecko/d{8}/.test(ua)){ engine.ver = RegExp["$1"]; engine.gecko = parseFloat(engine.ver); // 识别火狐 if(/Firefox/(S+)/.test(ua)){ browser.ver = RegExp["$1"]; browser.firefox = parseFloat(browser.ver); } }else if(/MSIE ([^;]+)/.test(ua)||(/Trident/(S+)/.test(ua)&&/rv:([^)]+))/.test(ua))){ // 识别IE engine.ver = browser.ver = RegExp["$1"]; engine.ie = browser.ie = parseFloat(engine.ver); } // 平台检测 var p = navigator.platform; system.win = p.indexOf("Win") === 0; system.mac = p.indexOf("Mac") === 0; system.xll = (p === "Xll") || (p.indexOf("Linux") === 0); // windows版本 if(system.win){ if(/Win(?:dows) ?([^do]{2})s?(d+.d+)?/.test(ua)){ if(RegExp["$1"] === "NT"){ switch(RegExp["$2"]){ case "5.0": system.win = "2000"; break; case "5.1": system.win = "XP"; break; case "6.0": system.win = "Vista"; break; case "6.1": system.win = "7"; break; default: system.win = RegExp.$2; break; } }else if(RegExp["$1"] === "9x"){ system.win = "ME"; }else{ system.win = RegExp["$1"]; } } } // 移动设备 system.iphone = ua.indexOf("iPhone") > -1; system.ipod = ua.indexOf("iPod") > -1; system.ipad = ua.indexOf("iPad") > -1; system.nokiaN = ua.indexOf("NokiaN") > -1; // windows Phone if(system.win ==="CE"){ system.winMobile = system.win; }else if(system.win === "Ph"){ if(/Windows Phone OS (d+.d+)/.test(ua)||/Windows Phone (d+.d+)/.test(ua)){ system.win = "windowsPhone"; system.winMobile = parseFloat(RegExp["$1"]); } } // 检测ios版本 if(system.mac && ua.indexOf("Mobile") > -1){ if(/CPU (?:iPhone)?OS (d+_d+)/.test(ua)){ system.ios = parseFloat(RegExp.$1.replace("_",".")); }else{ system.ios = 2; // 具体版本无法测试,默认为2 } } // 检测安卓版本 if(/Android (d+.d+)/.test(ua)&& !system.winMobile){ system.android = parseFloat(RegExp.$1); } // 平台检测 system.wii = ua.indexOf("Wii") > -1; system.ps = /playstation/i.test(ua); return { engine: engine, browser: browser, system: system }; }