浏览器的发展时间线如下:
- WorldWideWeb 1991 年
- Mosaic 1993年
- Netscape 1994年
- Opera 1995年
- IE 1995年 (一战)
- Safari 2003年
- Firefox 2004年 (二战)
- Chrome 2008年
- Edge 2015年
为什么所有的浏览器都姓 Mozilla/5.0
本文改编自:小东, [Blog]网站日志中显示Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari, http://madong.net.cn/index.php/2016/05/557/
◾ROUND.1 一切都从一个名叫 Mozilla 的浏览器开始
很久很久以前有一个浏览器名字叫 NCSA Mosaic。紧接着也出现了一个 Mozilla 的浏览器,意思是 Mosaic 终结者。后来 Mozilla 的正式发布版本是 Netscape (网景)。它把自己标称为:
Mozilla/1.0 (Win3.1)
^^^^^^^
由于 Netscape 支持框架显示,后来框架在大家中间流行起来了,但 Mosaic 不支持框架。
所以网站管理员们则通过 User-Agent 判断,如果是网景浏览器则进入框架 (HTML frame) 的页面,如果不是网景浏览器则进入没有框架的页面,用框架显示出来的网页要比没用框架的更好看。
// 伪代码
If "Mozilla" in UA:
load_HTML_Frame(HTML)
Else:
load_HTML()
但网景没有风光多久,微软也推出了自己的 IE 浏览器,并且 IE 浏览器也支持框架。但是很遗憾,因为 IE 的 User-Agent 中没有 Mozilla,所以网站管理员们不认识它,也就没有人理它。后来微软抓狂了,你们不就是只认识 User-Agent 头里有 Mozilla 字符的浏览器么,于是宣称 IE 是“兼容 Mozilla ”的,开始模仿网景的 User-Agent,把自己标称为:
Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)
^^^^^^^ ----
这样一来 IE 也有了 Mozilla (其实是伪装的···) 所以那些框架也能看到了。后来随着微软把浏览器捆绑进自己的操作系统里一起卖,随就爆发了浏览器大战。结果大家都很清楚,网景失败了。而微软大胜了,至今微软的 IE 依然影响着 W3C 影响着所有浏览器。
◾ROUND.2 渲染引擎 Gecko 横空出世,渲染出更好看的网页
网景失败后重生为 Mozilla,构造了 Gecko (渲染引擎),标称其为:
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1) Gecko/20020826
^^^^^^^ ^^^^^
Gecko 属于渲染引擎(Rendering Engine),表现优异。 Mozilla 开发了 Firefox,标称为:
Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7.5) Gecko/20041108 Firefox/1.0
^^^^^^^ ^^^^^ -------
并且 Firefox 表现也非常优秀,因为它也使用 Gecko 。由于 Gecko 的优秀,网站管理员们会判断浏览器是否是 Gecko 的,如果是则把更先进、更漂亮页面显示给这个浏览器,譬如现在的 HTML5。其他浏览器就没有这个待遇了。如果我判断是你 Firefox 的新版本则跳转到地址1,如果是 IE 则去地址2。
// 伪代码
If "Mozilla" in UA:
If "Gecko" in UA:
load_Rendering_Engine(HTML5)
Else:
load_HTML_Frame(HTML)
Else:
load_HTML()
看到 Gecko 能看到这么漂亮的页面,Linux 的平台的孩子们很伤心,因为他们创建的基于 KHTML 的 Konqueror 浏览器也跟 Gecko 一样优秀,但因为却不带有 Gecko 而不能被识别。结果 Konquerer 开始伪装自己“像 Gecko”,就可以看到更漂亮的网页,也有样学样地标称自己为:
Mozilla/5.0 (compatible; Konqueror/3.2; FreeBSD)(KHTML, like Gecko)
^^^^^^^ --------- ^^^^^
这个世界就抽风了。放眼望去,全是 Mozilla 和 Gecko ···
◾ROUND.3 当浏览器引擎(Rendering Engine)开始套娃
Apple 开发了 Safari 浏览器,使用的是 KHTML 渲染引擎,同时也增加了很多新特性,后来干脆另起炉灶叫做 WebKit 渲染引擎,但是它有希望能够看到那些为 KHTML 编写的网页,于是 Safari 也标称自己为:
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.5
^^^^^^^ ----------- ^^^^^ ------
场面就更加混乱了···
Google 也开发了自己的浏览器 Chrome,使用了 Webkit 作为渲染引擎,有点像 Safari,希望能看到为 Safari 编写的网页,于是决定装成 Safari ,宣称自己是:
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko)Chrome/0.2.149.27 Safari/525.13
^^^^^^^ ----------- ^^^^^ ------ ^^^^^^
最后。IE 伪装成 Mozilla(浏览器);WebKit 伪装成 KHTML,KHTML 伪装成 Gecko(渲染引擎)。Opera 伪装成上面任何浏览器,同时所有的浏览器又都宣称自己是 Mozilla。最终导致所有浏览器的 User_Agent 都是这个格式:
Mozilla/5.0 (平台) 引擎版本 浏览器版本号
User-Agent 的世界就颠成了现在的模样。
不同浏览器的伪装策略
Mosaic-Netscaps-IE
1993年,NCSA 发布了首款 Web 浏览器 Mosaic 。它的 User-Agent 字串非常简洁:
Mosaic/0.9
虽然当时由于它对操作系统和平台的依赖性,但是基本格式还是很简单明了。在文本中,斜杠前面是产品名称(可能会显示为 NCSA Mosaic 或是其他类似的字),斜杠后面是产品版本号。
Netscape Communications (网景) 开发了web浏览器 Mozilla (当时号称 Mosaic 杀手)。他们首款公开发行版本:Netscape Navigator 2 的 User-Agent 具有如下格式:
Mozilla/Version [Language] (Platform; Encryption)
Netscape 按之前的做法在 User-Agent 字串的前半部分使用了产品名称和产品版本,但在后面增加了下列信息:
Language:表示应用程序用的是哪个语言Platform:表示应用程序是在什么操作系统和/或平台中运行Encryption:表示应用程序包含了什么安全加密类型。其中的值可能是U(128位加密)、I(40位加密)、N(没加密)。由于 2019 年前后对于 HTTP 安全要求的提升,强制要求提供 U(128bit) 级加密,加密类型的信息也就失去了意义。目前这个字段已被废用。
Netscape Navigator 2 的 User-Agent 字串的示例:
Mozilla/2.02 [fr] (WinNT; I)
// Mozilla/2.02: Netscape Navigator 2.02
// [fr]: 法语
// WinNT: Windows NT
// I: 40 bit 加密
在当时,通过 User-Agent 字串中的产品名称,可以正确判断使用的是哪个web浏览器。Netscape Navigator 3、Internet Explorer 3。1996 年,Netscape Navigator 3 发布,它远远超过 Mosaic 成为当时最流行的web浏览器。而 User-Agent 字串只有些小的变化,去掉了语言部分,多了个放操作系统或 CPU 的可选信息。格式如下:
Mozilla/Version (Platform; Encryption [; OS-or-CPU description])
在 Windows 系统中,字串里面不会显示 OS 或 CPU 的信息。于是在 Windows 系统中 Netscape Navigator 3 的 User-Agent 长这样:
Mozilla/3.0 (Win95; U)
// Mozilla/3.0: Netscape Navigator 3
// Win95: Windows 95
// U: 128 bit 加密
Netscape Navigator 3 发布不久,微软公布了它的首款 Web 浏览器:IE 3 ,但是 Netscape 是当时首选浏览器,大多数服务器在加载页面前都会检查 User-Agent 是否为该款浏览器。IE 如果不兼容 Netscape 的 User-Agent,使用 IE 的用户就根本打不开这些页面,于是造就了如下格式:
Mozilla/2.0 (compatible; MSIE Version; Operating System)
Mozilla/2.0 (compatible; MSIE 3.02; Windows 95) // e.g.
由于当时的浏览器嗅探只查 User-Agent 字串中的产品名称部分,结果 IE 摇身一变被识别成了 Mozilla,伪装成 Netscape Navigator。这个做法引发了对浏览器识别的争论。从此以后,浏览器真正的版本埋没在了字串的中间。Netscape Communicator 4 、 Internet Explorer 4 至 8 。1997 年 8 月,Netscape Communicator 4 发布 (发布的名称中 Navigator 换成了 Communicator ),它的 User-Agent 字串格式与 3 版本一致。Windows 98 中 4 版本的 User-Agent 字串如下:
Mozilla/4.0 (Win98; I)Netscape
浏览器在更新时,版本也相应增加。4.79 版本的 User-Agent 字串如下:
Mozilla/4.79 (Win98; I)
微软发布 IE4 时,User-Agent 字串更新了版本,格式如下:
Mozilla/4.0 (compatible; MSIE Version; Operating System)
Mozilla/4.0 (compatible; MSIE 4.0; Windows 98) // e.g.
可以看出,Mozilla 的版本与 IE 实际的版本一致,这样就可以识别第 4 代浏览器了。但遗憾的是,不久 IE4.5 马上就发布了(只在 Mac 平台),虽然 Mozilla 版本仍是 4,但是 IE 的版本改成如下:
Mozilla/4.0 (compatible; MSIE 4.5; Mac_PowerPC)
此后,IE 的版本一直到 IE7 都沿用了这个模式。
而 IE8 的 User-Agent 字串添加了渲染引擎 (rendering engine) 版本:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
^^^^^^^
新增的渲染引擎非常重要!这样 IE8 以 MSIE 7.0 兼容模式运行时,Trident 版本保持不变,而原先 IE7 的 User-Agent 字串不包括 Trident 版本。这样可以区分 IE7 与 IE8 运行的兼容模式。
哈哈,别指望能从 Mozilla 版本中得到什么靠谱的信息。
Firefox (Gecko)
Gecko 是 Firefox 的渲染引擎。Gecko 首次开发是作为 Mozilla 浏览器 Netscape 6 的一部分。Netscape 6 的 User-Agent 字串的结构是面向未来的,新版本反应出从 4.x 版本的简单变得较为复杂,它的格式如下:
Mozilla/MozillaVersion (Platform; Encryption; OS-or-CPU; Language; PrereleaseVersion)Gecko/GeckoVersion ApplicationProduct/ApplicationProductVersion
为了更好的理解上面的 Gecko User-Agent 字串格式,下面来看看各种从基于 Gecko 浏览器中取得的字串。
# 在 Windows 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.1
# 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.11Mac 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
上面都是基于 Gecko 的浏览器所取得的 User-Agent 字串,区别只是版本有所不同。 Mozilla 版本 5.0 是自从首款基于 Gecko 发布后就一直不变,而且以后有可能也不会变。
Safari (WebKit)
2003年,Apple 宣布发布首款他们自主开发的 Web 浏览器:Safari 。它的渲染引擎叫 WebKit 。它是 Linux 中的 Web浏览器 Konqueror 渲染引擎 KHTML 的一个分支,几年后,WebKit 的开源吸引了渲染引擎的开发人员。
这款新浏览器和渲染引擎的开发人员也遇到了曾经 IE3 类似的问题:怎样才能融入主流而不被踢出局?答案是:在 User-Agent 字串中放详尽的信息,以便骗取网站的信任使它与其它流行的浏览器兼容。User-Agent 字串格式如下:
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 // e.g.
^^^^^^^ ----------- ^^^^^ ^^^^^ ------
这又是个挺长的 User-Agent 字串,其中包括的信息既有 Apple WebKit 的版本,也有 Safari 的版本。凡是基于 WebKit 的浏览器都将自己伪装成了 Mozilla 5.0 ,与基于 Gecko 浏览器完全一样。但 Safari 的版本是浏览器的构建版本号 (build number)。Safari 1.25 在 User-Agent 字串中号为 125.1 (如上所示)。Safari 3 的 User-Agent 字串包括了实际的 Safari 版本:
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/522.15.5 (KHTML, like Gecko) Version/3.0.3 Safari/522.15.5
其中的 (KHTML, like Gecko) 在 Safari 1.0 预览版本中就有了,这字串部分是最耐人寻味又饱受诟病。Apple 的野心是为了让开发人员把 Safari 当成 Gecko,所以采取了与当初微软 IE 一样的策略:Safari 是兼容 Mozilla 的,否则 Safari 用户会认为用的浏览器不受支持。
而其它基于 WebKit 的浏览器与 Safari 不同的是,没有上面说的这个情况,所以检测断定浏览器是否基于 WebKit 比看有没有明确标 Safari 更有用。
Konqueror (KHTML)
Konqueror 是款在 KDE Linux 桌面环境中的浏览器,基于 KHTML 开源渲染引擎。它只发布了在 Linux 的版本,但是拥有活跃的用户群。为了兼容性最大化,User-Agent 字串的格式也紧跟 IE 的后尘:
Mozilla/5.0 (compatible; Konqueror/Version; OS-or-CPU) Konqueror 3.2
为了与 WebKit 的 User-Agent 字串变化保持一致,它将 KHTML 作为它的标识:
Mozilla/5.0 (compatible; Konqueror/Version; OS-or-CPU) KHTML/KHTMLVersion (like Gecko)
Mozilla/5.0 (compatible; Konqueror/3.5; SunOS) KHTML/3.5.0 (like Gecko) //e.g.
^^^^^^^ ^^^^^
Konqueror 和 KHTML 的版本号比较一致,唯一的区别就是下点处不同,比如 Konquerer 3.5、KHTML 3.5.1。
Chrome (WebKit)
Google Chrome 浏览器以 WebKit 作为渲染引擎,JavaScript 引擎却用了另一种。最初发布的版本是 0.2,它的 User-Agent 字串格式是在 WebKit 信息的基础上又增加了如下:
Mozilla/5.0 (Platform; Encryption; OS-or-CPU; Language) AppleWebKit/AppleWebKitVersion (KHTML, like Gecko) Chrome/ChromeVersion Safari/SafariVersionChrome 0.2
User-Agent 信息的示例如下:
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.29 Safari/525.13
虽我不敢完全保证,但很可能 WebKit 版本和 Safari 版本总会保持同步。
Opera
Opera 浏览器默认 User-Agent 字串是现代浏览器中最合理的,它正确的标识了它自己及其版本。 在 Opera 8.0 前,它的 User-Agent 字串格式如下:
Opera/Version (OS-or-CPU; Encryption) [Language]
在 Windows XP 中 Opera 7.54 的 User-Agent 长这样:
Opera/7.54 (Windows NT 5.1; U) [en]Opera 8
后来 User-Agent 的语言标识移到了括号内:
Opera/Version (OS-or-CPU; Encryption; Language)
Opera/8.0 (Windows NT 5.1; U; en) // Windows XP + Opera 8
当时 Opera 做为主流浏览器之一,它的 User-Agent 是唯一使用产品名称和版本完全真实的标识了它自己。但是由于大量的浏览器嗅探代码在 Internet 上像蝗虫飞过般只吃标 Mozilla 产品名的 User-Agent,造成了 Opera 的 User-Agent 发生了完全的改变。你们不是只认 Mozilla 吗?那我就 Mozilla 给你们看!由此 Opera 也开始被 Mozilla 殖民。当时 Opera 9 的 User-Agent 有两种修改的方式。一种方式为半殖民地半 Opera,为了更方便的被解析,于是将自己标识为 Firefox 或 IE 浏览器,只不过 Opera 还是很倔强的在 UA 末尾附加了 Opera 字样及版本号。如下所示:
Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en)
^^^^^^^ ^^^^^ ^^^^^^^ ----- ^^^^^^^ ^^^^
仔细观察可以看出,上面这段 UA 根本就是由两段 UA 拼起来的。前一段 UA 是从 Firefox 2 偷过来的,后一段 UA 是从 IE 6 偷过来的两段 UA 中间还很倔强地加上了 Opera 字样及版本号。这样一来 Opera 可以被同时识别为 Firefox 或者 IE 了,同时也能识别出 Opera 浏览器地痕迹。但代价是原本清清爽爽的 UA 被鬼涂乱画成了这般德行。
另一种方法就更加地欺师灭祖。依然是将 User-Agent 字串标识伪装成 Firefox 或 IE,但同时去掉了 Opera 的标注。这样从字面上去区分 Opera 浏览器便成了“不可能完成的任务”。
结论
User-Agent 史可以说明曾对 User-Agent 嗅探说不的原因:IE 想要被识别为 Netscape 4,Konqueror 和 WebKit 想要被识别为 Firefox,Chrome 想要识别为 Safari。
这样使得除 Opera 外所有浏览器的 User-Agent 嗅探区别很小,想要从一堆茫茫浏览器海洋中找出有用的标识太少了。关于嗅探要记住:一款浏览器与其它浏览器是兼容的,这样造成了不能完全准确的断定是哪款浏览器。比如说 Chrome,它声称任何可以在 Safari 3 访问的网站 Chrome 也都可以访问,但是对检测 Chrome 没有一点用。为了浏览器的兼容——这便是这个声明的理由。