Javascript高级编程学习笔记(34)—— 客户端检测(3)用户代理检测

时间:2022-09-23 22:50:12

用户代理检测

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

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

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

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

那么如何进行检测呢?

我之前的文章,讲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&lpar;4&rpar; WebGL上下文&lpar;2&rpar;

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

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

    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. ASP&period;NET 5 Beta 8 发布

    ASP.NET 5 的路线图(详见 ASP.NET 5 Schedule and Roadmap : https://github.com/aspnet/home/wiki/roadmap ):Bet ...

  2. xgboost原理及应用

    1.背景 关于xgboost的原理网络上的资源很少,大多数还停留在应用层面,本文通过学习陈天奇博士的PPT 地址和xgboost导读和实战 地址,希望对xgboost原理进行深入理解. 2.xgboo ...

  3. Java7并发编程实战(一) 线程的中断

    控制线程中断的方法一般常规是定义一个布尔值,然后while(布尔值) 去执行,当想停止该线程时候,把布尔值设为false. 这里我们来看第二种,Interrupt 该例子模拟一个线程从1打印到10,然 ...

  4. Activiti 学习笔记记录

    官方在线用户手册(英文版):http://activiti.org/userguide/index.html 中文用户手册:http://www.mossle.com/docs/activiti/in ...

  5. ASP&period;NET MVC- 使用PageList&period;Mvc分页

    ASP.NET MVC中进行分页的方式有多种,在NuGet上有提供使用PagedList.PagedList.Mvc进行分页. 1. 通过NuGet引用PagedList.Mvc 在安装引用Paged ...

  6. HT518V311

    HT518V311.rar

  7. 测试开发之前端——No3&period;HTML5中的标准属性

    HTML5的标准属性 属性 值 描述 accesskey character 规定访问元素的键盘快捷键 class classname 规定元素的类名(用于规定样式表中的类). contentedit ...

  8. java 重新抛出异常

    一.有时希望把刚捕获的异常重新抛出,尤其时在使用Exception捕获所以异常的时候,既然已经得到了对当前异常对象的引用,可以重新把它抛出: catch(Exception e){ System.ou ...

  9. EF5&plus;MVC4系列&lpar;9&rpar; Razor视图引擎的核心原理&semi;&commat;符号的使用&semi;输出html的转义

    一:Razor视图引擎的核心原理 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项 ,他是一个视图引擎 他的核心原理,就是当读取到 @符号的时候,就认为这是开始 ...

  10. P2979 &lbrack;USACO10JAN&rsqb;奶酪塔Cheese Towers

    P2979 [USACO10JAN]奶酪塔Cheese Towers 背包dp 不过多了一个大奶酪可以压扁其他奶酪的 一开始写了个暴力82分.贪心的选择 然后发现,有如下两种规律 要么最优都是小奶酪, ...