# 能力检测
代码语言:javascript复制测试浏览器是否支持某种特性
// 基本模式
if (object.propertyInQuestion) {
// 使用object.propertyInQuestion
}
- 能力检测的关键
- 先检测最常用的方式,可避免无谓检测
- 必须检测切实需要的特性
# 安全能力检测
能力检测最有效的场景是检测能力是否存在的同时,验证其是否能够展现出预期的行为。
# 基于能力检测进行浏览器分析
恰当地使用能力检测可以精准地分析运行代码的浏览器。使用能力检测而非用户代理检测的优点在于,伪造用户代理字符串很简单,而伪造能够欺骗能力检测的浏览器特性却很难。
- 检测特性 可以按照能力将浏览器归类。如果你的应用程序需要使用特定的浏览器能力,那么最好集中检测所有能力,而不是等到用的时候再重复检测。
- 检测浏览器 可以根据对浏览器特性的检测并与已知特性对比,确认用户使用的是什么浏览器。这样可以获得比用户代码嗅探(稍后讨论)更准确的结果。
- 能力检测的局限 通过检测一种或一组能力,并不总能确定使用的是哪种浏览器。
# 用户代理检测
用户代理检测通过浏览器的用户代理字符串确定使用的是什么浏览器。用户代理字符串包含在每个 HTTP 请求的头部,在 JavaScript 中可以通过 navigator.userAgent 访问。在服务器端,常见的做法是根据接收到的用户代理字符串确定浏览器并执行相应操作。而在客户端,用户代理检测被认为是不可靠的,只应该在没有其他选项时再考虑。 用户代理字符串最受争议的地方就是,在很长一段时间里,浏览器都通过在用户代理字符串包含错误或误导性信息来欺骗服务器。
# 用户代理的历史
- 早期浏览器
// 早期浏览器
// Mosaic/0.9
// Netscape Navigator 2
// Mozilla/Version [Language] (Platform;Encryption)
// 语言 操作系统或平台;安全加密类型
- Netscape Navigator 3 和 IE3
// Mozilla/Version (Platform;Encryption[; OS-or-CPU description])
// Mozilla/3.0 (Win95; U) => Netscape Navigator 3 运行在Windows95上采用128位加密
// IE3 兼容Netscape 用户代理字符串
// Mozilla/2.0 (compatible; MSIE Version; Operating System)
// Mozilla/2.0 (compatible; MSIE 3.02; Windows 95) => 伪装Mozilla的IE
- Netscape Communicator 4 和 IE 4~8
// Mozilla/Version (Platform; Encryption [; OS-or-CPU description])
// Mozilla/4.0 (Win98; I)
// Mozilla/4.79 (Win98; I) 发布补丁
// IE4~7
// Mozilla/4.0 (compatible; MSIE Version; Operating System)
// Mozilla/4.0 (compatible; MSIE 4.0; Windows 98)
// Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
// IE8 添加了 浏览器渲染引擎代号
// Mozilla/4.0 (compatible; MSIE Version; Operating System; Trident/Trident Version)
// Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
// Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0) => IE8运行在IE7兼容模式
// IE9
// Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
// Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0) => IE9运行在IE7兼容模式
- Gecko
代码语言:javascript复制Gecko 渲染引擎是 Firefox 的核心。 Gecko 最初是作为通用 Mozilla 浏览器(即后来的 Netscape 6)的一部分开发的。有一个针对 Netscape 6 的用户代理字符串规范,规定了未来的版本应该如何构造这个字符串。
Mozilla/MozillaVersion (Platform; Encryption; OS-or-CPU; Language; PrereleaseVersion)
Gecko/GeckoVersion
ApplicationProduct/ApplicationProductVersion
含义
- MozillaVersion(必需):Mozilla 版本
- Platform(必需):浏览器所在的平台。可能的值包括 Windows、 Mac 和 X11(UNIX X-Windows)
- Encryption(必需):加密能力:U 表示 128 位,I 表示 40 位,N 表示无加密
- OS-or-CPU(必需):浏览器所在的操作系统或计算机处理器类型。
- Windows 平台是Windows 的版本(如 WinNT、 Win95)
- Mac 平台是 CPU 类型(如 68k、 PPC for PowerPC 或 MacIntel)
- X11 平台是通过 uname-sm 命名得到的 UNIX 操作系统名
- Language(必需):浏览器的目标使用语言
- Prerelease Version(可选):最初的设想是 Mozilla 预发布版的版本号,现在表示 Gecko 引擎的版本号
- GeckoVersion(必需):以 yyyymmdd 格式的日期表示的 Gecko 渲染引擎的版本
- ApplicationProduct(可选): 使用 Gecko 的产品名称。可能是 Netscape、 Firefox 等
- ApplicationProductVersion(可选): ApplicationProduct 的版本,区别于 MozillaVersion 和 GeckoVersion
// Windowx XP 上的 Netscape 6.21
// Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4) Gecko/20011128 Netscape6/6.2.1
// Linux 上的 SeaMonkey 1.1a
// Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1b2) Gecko/20060823 SeaMonkey/1.1a
// Windows XP 上的 Firefox 2.0.0.11:
// Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11
// Mac OS X 上的 Camino 1.5.1:
// Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en; rv:1.8.1.6) Gecko/20070809 Camino/1.5.1
在 Firefox 4 发布时, Mozilla 简化了用户代理字符串
- 去掉了语言标记
- 在浏览器使用强加密时去掉加密标记
- 去掉了 Windows 平台上的平台标记,因为跟 OS-or-CPU 部分重复了
- GeckoVersion 固定为"Gecko/20100101"
// Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox 4.0.1
- WebKit
代码语言:javascript复制2003 年,苹果宣布将发布自己的浏览器 Safari。 Safari 的渲染引擎叫 WebKit,是基于 Linux 平台浏览器 Konqueror 使用的渲染引擎 KHTML 开发的。几年后, WebKit 又拆分出自己的开源项目,专注于渲染引擎开发。
// Mozilla/5.0 (Platform; Encryption; OS-or-CPU; Language) AppleWebKit/AppleWebKitVersion (KHTML, like Gecko) Safari/SafariVersion
// Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1
- Konqueror
代码语言:javascript复制Konqueror 是与 KDE Linux 桌面环境打包发布的浏览器,基于开源渲染引擎 KHTML。为实现最大化兼容,Konqueror 决定采用 Internet Explore 的用户代理字符串格式
Mozilla/5.0 (compatible; Konqueror/Version; OS-or-CPU)
代码语言:javascript复制Konqueror 3.2 为了与 WebKit 就标识为 KHTML 保持一致,也对格式做了一点修改
Mozilla/5.0 (compatible; Konqueror/Version; OS-or-CPU) KHTML/KHTMLVersion (like Gecko)
- Chrome
代码语言:javascript复制谷歌的 Chrome 浏览器使用 Blink 作为渲染引擎,使用 V8 作为 JavaScript 引擎。 Chrome 的用户代理字符串包含所有 WebKit 的信息,另外又加上了 Chrome 及其版本的信息
Mozilla/5.0 (Platform; Encryption; OS-or-CPU; Language) AppleWebKit/AppleWebKitVersion (KHTML, like Gecko) Chrome/ChromeVersion Safari/SafariVersion
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7
- Opera
Opera8 之前
Opera/Version (OS-or-CPU; Encryption) [Language]
Opera/7.54 (Windows NT 5.1; U) [en]
Opera 8
Opera/Version (OS-or-CPU; Encryption; Language)
Opera/8.0 (Windows NT 5.1; U; en)
Opera 9
Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50
Opera 10
Opera/9.80 (OS-or-CPU; Encryption; Language) Presto/PrestoVersion Version/Version
Opera/9.80 (Windows NT 6.1; U; en) Presto/2.6.30 Version/10.63
Opera 52
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.64
- iOS与Android
代码语言:javascript复制iOS 和 Android 移动操作系统上默认的浏览器都是基于 WebKit 的,因此具有与相应桌面浏览器一样的用户代理字符串。
iOS
Mozilla/5.0 (Platform; Encryption; OS-or-CPU like Mac OS X; Language)
AppleWebKit/AppleWebKitVersion (KHTML, like Gecko) Version/BrowserVersion
Mobile/MobileVersion Safari/SafariVersion
Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)
AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16
Android
Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91)
AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
# 浏览器分析
伪造用户代理
代码语言:javascript复制console.log(window.navigator.userAgent);
// Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/65.0.3325.181 Safari/537.36
window.navigator.__defineGetter__('userAgent', () => 'foobar');
console.log(window.navigator.userAgent);
// foobar
分析浏览器 通过解析浏览器返回的用户代理字符串,可以极其准确地推断出下列相关的环境信息:
- 浏览器
- 浏览器版本
- 浏览器渲染引擎
- 设备类型(桌面/移动)
- 设备生产商
- 设备型号
- 操作系统
- 操作系统版本
# 软件与硬件检测
# 识别浏览器与操作系统
- navigator.oscpu 用户代理字符串中操作系统/系统架构相关信息
- navigator.vendor 浏览器开发商信息
- navigator.platform 浏览器所在的操作系统
- screen.colorDepth 和 screen.pixelDepth 显示器每像素颜色的位深
- screen.orientation Screen Orientation API 定义的屏幕信息
# 浏览器元数据
- Geolocation API 让浏览器脚本感知当前设备的地理位置
- Connection State 和 NetworkInformation API 浏览器会跟踪网络连接状态并以两种方式暴露这些信息:连接事件和 navigator.onLine 属性
- Battery Status API 浏览器可以访问设备电池及充电状态的信息
# 硬件
- navigator.hardwareConcurrency 浏览器支持的逻辑处理器核心数量
- navigator.deviceMemory 设备大致的系统内存大小,包含单位为 GB 的浮点数
- navigator.maxTouchPoints 返回触摸屏支持的最大关联触点数量,包含一个整数值