用户代理检测

前面的文章介绍的是如何检测浏览器对某一功能的支持情况

但是在实践中我们有些时候免不了需要知道用户到底是用的什么浏览器对我们的站点进行访问

这也是统计用户行为的一部分

用户代理检测这种方式就是用于检测用户访问所使用的浏览器的

那么如何进行检测呢?

我之前的文章,讲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
};
}

Javascript高级编程学习笔记(34)—— 客户端检测(3)用户代理检测的更多相关文章

  1. Javascript高级编程学习笔记(32)—— 客户端检测(1)能力检测

    能力检测 浏览器厂商虽然在实现公共接口方面投入了大量的精力 但是每种浏览器仍旧存在许多差异 为了让网页能跨浏览器的运行,对浏览器差异做的兼容处理自然无法避免 其中最常用的也就是我们现在所说的能力检测 ...

  2. Javascript高级编程学习笔记(33)—— 客户端检测(2)怪癖检测

    怪癖检测 和能力检测类似,但其目标不同 能力检测的目的是判断浏览器支不支持某种能力 而怪癖检测的目的是判断浏览器是否存在某些缺陷 这种时候需要我们执行一段代码来判断浏览器是否有这样的缺陷 或者说是怪癖 ...

  3. Javascript高级编程学习笔记(98)—— WebGL(4) WebGL上下文(2)

    错误 Javascript与WebGL之间的一个最大区别在于,WebGL的操作一般不会抛出错误 如果希望获取WebGL的错误信息,那么就需要手动调用  gl.getError() 方法 该方法会返回以 ...

  4. Javascript高级编程学习笔记(97)—— WebGL(3) WebGL上下文(1)

    WebGL上下文 在支持WebGL的浏览器中,WebGL的名字为 "experimental-webgl",这是由于 webgl 的规范仍未制定完成 制定完成后名字就会改为简单的 ...

  5. Javascript高级编程学习笔记(75)—— 表单(3)表单字段

    表单字段 表单作为web应用中不可或缺的一部分,当然也是可以使用原生的 DOM 元素来访问的 除了标准的访问方式之外,每个表单都拥有一个 elements 属性,该属性保存着该表单所有 表单元素 的集 ...

  6. Javascript高级编程学习笔记(64)—— 事件(8)键盘与文本事件

    键盘与文本事件 用户在使用键盘时会触发键盘事件 “DOM2级事件”最初规定了键盘事件,但是最后在定稿时又删除了相应内容 所以键盘事件被放入了DOM3级事件的规范中 总的来说有三个键盘事件: keydo ...

  7. Javascript高级编程学习笔记(53)—— DOM2和DOM3(5)遍历

    遍历 “DOM2级遍历和范围” 定义了两个用于辅助完成顺序遍历的DOM结构类型 NodeIterator 和 TreeWalk 上述两种类型可以基于给定起点的DOM结构执行深度优先的遍历操作 对于检测 ...

  8. Javascript高级编程学习笔记(49)—— DOM2和DOM3(1)DOM变化

    DOM变化 我们知道DOM有许多的版本,其中DOM0和DOM2这两个级别以对事件的纳入标准而为人所知 但是呢,这里不讲事件,在后面会有专门和事件有关的部分作为详细讲解 这里就只讲一下DOM2和DOM3 ...

  9. Javascript高级编程学习笔记(31)—— BOM(5)screen、history对象

    screen对象 screen对象应该是BOM对象中最不常用的对象了 其主要用于提供客户端的显示能力信息 包括浏览器外部显示的信息,和像素的宽高等 这个对象的主要用于检测客户端能力,一般不会影响功能 ...

随机推荐

  1. CentOS7下开放端口

    memcached等服务启动后,外网默认是无法访问的,因为防火墙不允许,所以要开启防火墙,让其可以访问这些端口号. 方法一:使用firewall 1.运行命令:firewall-cmd --get-a ...

  2. c#dev gridview 设置隔行换色等

    1:禁止gridview编辑 2:隔行换色 介绍一些常用的gridcontrol设置. 1.设置隔行变色.首先设置显示隔行变色,步骤:OptionsView-->EnableAppearance ...

  3. pip install rrdtool

    fatal error: rrd.h: No such file or directory apt-get install librrd-dev

  4. sql语句性能优化

    需要的准备知识 1最左前缀匹配 mysql会一直向右匹配直到遇到范围查询(>.<.between.like)就停止匹配, 对于where条件 a = 1 and b> 2 and c ...

  5. spring Resource(转)

    http://blog.csdn.net/u011225629/article/details/47143075

  6. EmWin 接触---基础函数

    创建对话框,需求两个基本要素:资源表和对话框过程.对话框可以基于阻塞(使用 GUI_ExecDialogBox())或非阻塞(使用 GUI_CreateDialogBox())方式创建.以下为例: G ...

  7. jquery基础知识随笔

    <html> <head> <script type="text/javascript" src="/jquery/jquery.js&qu ...

  8. 渗透测试的理论部分4——开放式Web应用程序安全项目

    开放式Web应用程序安全项目(Open Web Application Security Project OWASP) 定期退出Top 10 project(排名前十的安全隐患防守规则) 公开了编写安 ...

  9. Python_day8

    多态 class Animal(object): def run(self): print('animal is running') class Dog(Animal): def run(self): ...

  10. java开发过程中,报错Dangling meta character '*' near index 0,解决办法

    1.split方法转化字符串为数组: String[] strPicArr = map.get("hw_pic").toString().split("*"); ...