说说 JavaScript 对用户代理的检测技术(附完整源代码)
2017-04-18 15:14
405 查看
用户代理检测指的是,检测用户代理字符串来确定用户实际使用的浏览器。在服务端,用户代理检测是一种常见且广为让人接受的方式;但是,在客户端,用户代理检测是一种万不得已才使用的方法,它经常被放在能力检测和怪癖检测之后。可以通过 navigator.userAgent 得到用户代理字符串。
用户代理经常跟电子欺骗联系在一起,因为浏览器会在自己的用户代理字符串中加入一些错误或者误导性的信息,来欺骗服务器。
上面的代码很脆弱,因为如果 IE 有了新版本,就必须更新代码。建议使用相对版本号作为条件判断:
为了不在全局作用域中添加多余的变量,我们使用模块增强模式来封装检测脚本,基础结构如下:
匿名函数内部定义了一个局部变量 engine,它是一个包含默认设置的对象字面量。如果检测到当前的浏览器的呈现引擎类型,就以浮点数值的格式将引擎的版本号写入相应的属性(大于 0)。引擎的完整版本号(字符串)写入 ver 属性。这样设计后,可以像这样写条件判断语句:
检测顺序很重要,因此第一步是识别 Opera,因为它可能完全模仿其他浏览器:
第二步检测 WebKit,它有一个独一无二的 “AppleWebKit”:
第三步检测 KHTML,,它也有一个独一无二的 “Gecko”,早期的版本有一个 “Konqueror”:
派出了 Webkit 和 KHTML 之后,就可以准确地检测出 Gecko,它的版本号出现在字符串“rv:”的后面:
最后是检测 IE:
这里正则表达式中的取反符号,是为了取得不是分号的所有字符。
由于大多数浏览器与其呈现引擎密切相关,所以下面的检测浏览器的代码与检测呈现引擎的代码是混合在一起的:
可以这样使用上面设计的代码:
这样检测平台:
这样使用:
这样检测:
iOS 复杂些:
检测 Android 版本:
检测诺基亚 N 系列手机:
然后这样使用:
最后是 Windows Mobile(Windows CE),:
这样检测:
不能直接准确地使用能力检测和怪癖检测。
同一种浏览器在不同平台下具有不同的能力。
为了跟踪分析等目的需要知道确切的浏览器类型。
用户代理经常跟电子欺骗联系在一起,因为浏览器会在自己的用户代理字符串中加入一些错误或者误导性的信息,来欺骗服务器。
1 用户代理字符串检测技术
一般情况下,直到呈现引擎和最低限度的版本就可以决定是否可以使用某些操作方法了。if (isIE6 || isIE7){ //不推荐 }
上面的代码很脆弱,因为如果 IE 有了新版本,就必须更新代码。建议使用相对版本号作为条件判断:
if (isVer >=6){ //代码 }
1.1 识别呈现引擎
目前有这五种主要的呈现引擎:IE、Gecko、Webkit、KHTML、Opera。为了不在全局作用域中添加多余的变量,我们使用模块增强模式来封装检测脚本,基础结构如下:
var client = function () { var engine = { //呈现引擎 ie: 0, gecko: 0, webkit: 0, khtml: 0, opera: 0, //具体版本号 ver: null }; return { engine: engine }; }
匿名函数内部定义了一个局部变量 engine,它是一个包含默认设置的对象字面量。如果检测到当前的浏览器的呈现引擎类型,就以浮点数值的格式将引擎的版本号写入相应的属性(大于 0)。引擎的完整版本号(字符串)写入 ver 属性。这样设计后,可以像这样写条件判断语句:
if (client.engine.ie){ //针对 IE } else if (client.engine.gecko > 1.5){ if (client.engine.gecko.ver == "1.8.1"){ //针对这一版本执行某些操作 } }
检测顺序很重要,因此第一步是识别 Opera,因为它可能完全模仿其他浏览器:
if (window.opera) {//opera 引擎 engine.ver = window.opera.version();//opera 7.6 及更高 engine.opera = parseFloat(engine.ver); }
第二步检测 WebKit,它有一个独一无二的 “AppleWebKit”:
else if (/AppleWebKit\/(\S+)/.test(ua)) {//webkit 引擎 engine.ver = RegExp["$1"];//使用捕获组获得版本号 engine.webkit = parseFloat(engine.ver); }
第三步检测 KHTML,,它也有一个独一无二的 “Gecko”,早期的版本有一个 “Konqueror”:
else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) {//khtml 引擎 engine.ver = RegExp["$1"]; engine.khtml = parseFloat(engine.ver); }
派出了 Webkit 和 KHTML 之后,就可以准确地检测出 Gecko,它的版本号出现在字符串“rv:”的后面:
else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) {//gecko 引擎 engine.ver = RegExp["$1"]; engine.gecko = parseFloat(engine.ver); }
最后是检测 IE:
else if (/MSIE ([^;]+)/.test(ua)) {//ie 引擎 engine.ver = RegExp["$1"]; engine.ie = parseFloat(engine.ver); }
这里正则表达式中的取反符号,是为了取得不是分号的所有字符。
1.2 识别浏览器
为 client 对象添加了新属性:var client = function () { ... var browser = { //浏览器 ie: 0, firefox: 0, safari: 0, konq: 0, opera: 0, chrome: 0, //具体版本号 ver: null }; ... return { engine: engine, browser:browser }; }
由于大多数浏览器与其呈现引擎密切相关,所以下面的检测浏览器的代码与检测呈现引擎的代码是混合在一起的:
//检测呈现引擎、平台和设备 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)) {//webkit 引擎 engine.ver = RegExp["$1"]; engine.webkit = parseFloat(engine.ver); //先区分 Chrome 与 Safari 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)) {//khtml 引擎 engine.ver = browser.ver = RegExp["$1"]; engine.khtml = browser.konq = parseFloat(engine.ver); } else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) {//gecko 引擎 engine.ver = RegExp["$1"]; engine.gecko = parseFloat(engine.ver); if (/Firefox\/(\S+)/.test(ua)) {//是 Firefox browser.ver = RegExp["$1"]; browser.firefox = parseFloat(browser.ver); } } else if (/MSIE ([^;]+)/.test(ua)) {//ie 引擎 engine.ver = browser.ver = RegExp["$1"]; engine.ie = browser.ie = parseFloat(engine.ver); }
可以这样使用上面设计的代码:
if (client.engine.webkit){//WebKit 引擎 if (client.browser.chrome){ //Chrome } else if (client.browser.safari){ //Safari } } else if (client.engine.gecko){ if (client.browser.firefox){ //Firefox }else { //其他以 gecko 为呈现引擎的浏览器 } }
1.3 识别平台
为 client 对象添加了新属性:var client = function () { ... //平台 var system = { win: false, mac: false, x11: false, }; ... return { engine: engine, browser:browser, system: system }; }
这样检测平台:
//识别平台 var p = navigator.platform; system.win = p.indexOf("Win") == 0; system.mac = p.indexOf("Mac") == 0; system.x11 = (p.indexOf("X11") == 0) || (p.indexOf("Linux") == 0);
1.4 识别 Windows 操作系统
由于不同的浏览器在不同的 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 = "NT"; break; } } } else if (RegExp["$1"] == "9x") { system.win = "ME"; } else { system.win = RegExp["$1"]; } }
这样使用:
if (client.system.win){ if (client.system.win == "XP"){ //XP }else if (client.system.win == "7"){ //win7 } }
1.5 识别移动设备
为 system 对象添加新属性:var client = function () { ... //平台 var system = { ... //移动设备 iphone: false, ipod: false, ipad: false, ios: false, android: false, nokiaN: false, winMobile: false }; ... return { engine: engine, browser:browser, system: system }; }
这样检测:
//识别移动设备 system.iphone = ua.indexOf("iPhone") > -1; system.ipod = ua.indexOf("iPod") > -1; system.ipad = ua.indexOf("iPad") > -1;
iOS 复杂些:
//检测 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;//检测不出,所以猜测是更早的版本,比较稳妥 } }
检测 Android 版本:
//检测 Android 版本 if (/Android (\d+\.\d+)/.test(ua)) { system.android = parseFloat(RegExp.$1); }
检测诺基亚 N 系列手机:
//检测诺基亚 N 系列手机 system.nokiaN = ua.indexOf("NokiaN") > -1;
然后这样使用:
if (client.engine.webkit){ if (client.system, iOS){ //iOS }else if (client.system.android){ //Android } }
最后是 Windows Mobile(Windows CE),:
if (system.win == "CE") {//Windows Mobile 5.0 以及之前版本 system.winMobile = system.win; } else if (system.win == "Ph") {//Windows Mobile 5.0 以后版本 if (/Windows Phone OS (\d+.\d+)/.test(ua)) { system.win = "Phone"; system.winMobile = parseFloat(RegExp["$1"]); } }
1.6 识别游戏系统
为 system 对象添加新属性:var client = function () { ... //平台 var system = { ... //游戏系统 wii: false, ps: false }; ... return { engine: engine, browser:browser, system: system }; }
这样检测:
//识别游戏系统 system.wii = ua.indexOf("Wii") > -1; system.ps = /playstation/i.test(ua);
2 完整代码
var client = function () {
//呈现引擎
var engine = {
ie: 0,
gecko: 0,
webkit: 0,
khtml: 0,
opera: 0,
//具体版本号
ver: null
};
//浏览器
var browser = {
ie: 0,
firefox: 0,
safari: 0,
konq: 0,
opera: 0,
chrome: 0,
//具体版本号
ver: null
};
//平台
var system = {
win: false,
mac: false,
x11: false,
//移动设备
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)) {//webkit 引擎 engine.ver = RegExp["$1"]; engine.webkit = parseFloat(engine.ver); //先区分 Chrome 与 Safari 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)) {//khtml 引擎 engine.ver = browser.ver = RegExp["$1"]; engine.khtml = browser.konq = parseFloat(engine.ver); } else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) {//gecko 引擎 engine.ver = RegExp["$1"]; engine.gecko = parseFloat(engine.ver); if (/Firefox\/(\S+)/.test(ua)) {//是 Firefox browser.ver = RegExp["$1"]; browser.firefox = parseFloat(browser.ver); } } else if (/MSIE ([^;]+)/.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.x11 = (p.indexOf("X11") == 0) || (p.indexOf("Linux") == 0);
//识别 Windows 操作系统
console.log("ua:" + ua);
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 = "NT"; 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;
//检测 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;//检测不出,所以猜测是更早的版本,比较稳妥 } }
//检测 Android 版本 if (/Android (\d+\.\d+)/.test(ua)) { system.android = parseFloat(RegExp.$1); }
//检测诺基亚 N 系列手机 system.nokiaN = ua.indexOf("NokiaN") > -1;
//windows mobile
if (system.win == "CE") {
system.winMobile = system.win;
} else if (system.win == "Ph") {
if (/Windows Phone OS (\d+.\d+)/.test(ua)) {
system.win = "Phone";
system.winMobile = parseFloat(RegExp["$1"]);
}
}
//识别游戏系统 system.wii = ua.indexOf("Wii") > -1; system.ps = /playstation/i.test(ua);
return {
engine: engine,
browser: browser,
system: system
};
}();
3 使用方法
应该优先使用能力检测和怪癖检测,用户代理检测方法尽量只用作最后检测的手段。它一般适用于以下情形:不能直接准确地使用能力检测和怪癖检测。
同一种浏览器在不同平台下具有不同的能力。
为了跟踪分析等目的需要知道确切的浏览器类型。
相关文章推荐
- javascript 用户代理字符串检测技术-
- JavaScript检测用户代理字符串
- 完整的用户代理字符串检测脚本
- 【javascript】浏览器用户代理检测脚本实现
- javascript浏览器用户代理检测脚本实现方法
- 完整的用户代理字符串检测脚本
- javascript——用户代理(环境)检测
- javascript用户代理检测
- Javascript检测用户注册信息
- JavaScript密码强度检测源代码
- Javascript检测用户注册信息
- 检测用户是否禁用JavaScript的原理分析及解决方案
- JavaScript 常见安全漏洞及自动化检测技术
- 完整FusionChart技术的报表源代码和分析
- Internet Explorer® 8 之后,您可使用自动代理和自动检测功能,全局更改一些浏览器设置,而无需更改每个用户的计算机
- javascript打印完整金字塔型_完整菱形_空心菱形_思路算法详解_js源代码
- 浏览器用户代理检测
- 基于用户代理的缓存技术,对手机网站同样有效!
- JavaScript密码强度检测源代码
- "爱说说"技术原理:前端Javascript优化技巧(四)