几个礼拜之前,我谈论了特征检测和浏览器检测。这篇帖子提到了一点点嗅探User-agent,评论也跟着探讨。我主张user-agent嗅探是一种非常重要的技术,在罕见场合当你需要隐藏后端接口的时候,可以尝试用它。在你准备做那之前,了解为什么user-agent字符检测会被认为是一项不精确的技术对你是非常有用的。为了做到这一点,你需要看一下User-agent这几年的进化历史。
下面,从我的《Web开发者要掌握的专业JavaScript技术》一书中,截取了关于user-agent历史的一段删减部分。
早期浏览器
在1993年,NCSA发布了第一个web浏览器,Mosaic。它的User-agent真的很简单,采取类似这样的格式:Mosaic/0.9
虽然,这种user-agent在不同的操作系统和平台上显示出多样性,但是这种基本格式是简单的直截了当的。简写的文字指明了产品的名称(有些时候显示NCSA Mosaic,有时候会已一些衍生名来替代),跟在/后面的内容是产品的版本。
在NC发展web浏览器之初,给它取了个代号:Mozilla("Mosaic Killer"的简写)。Netscape Navigator 2 作为第一个公开的有效的版本,它的user-agent格式是这样的:
Mozilla/Version [语言(language)] (兼容平台(Platform); 安全加密(Encryption))
网景公司保留了产品名臣和版本号作为user-agent第一部分的传统,但是在后面接着增加了以下信息:
1.语言 - 让浏览器优先使用指定的语言工作
2.平台/操作系统 - 应用依赖的操作系统或者平台
3.安全加密 - 安全加密的种类,它的值可能是:U(128-bit加密),I(40-bit 加密),N(没有加密)
Netscape Navigator 2 典型的user-agent格式像是这样: Mozilla/2.02 [fr] (WinNt;I)
这个user-agent说明浏览器用的是Netscape Navigator 2.02 版本,用在讲法语的国家,以40-bit安全加密的方式运行在Windows NT操作系统中。这时期,几乎很容易的通过观察user-agent中的产品名称,了解目前在用什么浏览器。
Netscape Navigator 3 和 IE 3
1996年,网景浏览器3发布,马上超越Mosaic成为最流行的浏览器。这时期的user-agent只进行了一小点改动,移除了languag特征,同时增加了另一特征:操作系统或者系统的CPU介绍。这时候的user-agent格式如下:
Mozilla/Version (Platform; Encryption [; OS-or-CPU description])
在Windows系统中运行的网景浏览器3的user-agent典型的例子就像这样:
Mozilla/3.0 (Win95; U)
这串user-agent说明了网景浏览器3运行在Windows95中,通过128位 安全加密。你会发现,在Windows 系统中,会忽视操作系统或者CPU的介绍。
在网景浏览器3发布后不就,微软发布了他们的第一个公开有效的浏览器IE3。那段时期,因为网景浏览器的高市场占有率,许多服务器会优先为网景浏览器提供网页服务。因此,IE就成了收留无法访问页面的菜鸟浏览器,就此他们决定自己创造一个user-agent,它可以兼容网景浏览器user-agent。结果他们做到了,这个user-agent就像这样: Mozilla/2.0 (compatible; MSIE Version; Operating System)
举个例子,运行在Windows 95 平台上的IE3.02的user-agent就像这样:Mozilla/2.0 (compatible; MSIE 3.02; Windows 95)
因为在那时期,大多数浏览器嗅探技术主要是获取user-agent的名称特征,所以IE成功的把自己装扮成Mozilla,就同网景浏览器一样。这一举动引发了许多争论,因为它打破了浏览器鉴别规则。长远来看,真实的浏览器信息被埋藏在了中间的字符串信息中。
Netscape Communicator 4 和 IE4-IE8
1997年8月,网景浏览器4发布了(这一版本名字发生了变化,从Navigator 变成了 Communicator)。网景选择将网景浏览器4的user-agent格式保持和上一版本一致。在windows 98 机器上,4版本的user-agent格式就像这样:Mozilla/4.0 (Win98; I) 。
随着网景发布补丁修复浏览器的同时,浏览器版本号也随之增加,4.79版本的user-agent就像这样:Mozilla/4.79 (Win98; I)
当微软发布IE4的时候,它的user-agent做了重要跟新,获取的格式如:Mozilla/4.0 (compatible; MSIE Version; Operating System)
举个在Windows 98下运行的IE4浏览器,返回的user-agent格式就像这样:Mozilla/4.0 (compatible; MSIE 4.0; Windows 98)
大家可以看到,较上一版本,变动是同步返回Mozilla版本和真实的IE版本,由于这一变动,可以轻易的鉴别第四代浏览器。可惜,IE在接下来的升级中没有同步返回Mozilla版本。就像IE4.5(只发布在Macs上),IE版本变成了4.5,但是Mozilla版本仍旧返回是4:Mozilla/4.0 (compatible; MSIE 4.5; Mac_PowerPC)
在接下来的IE版本,甚至是IE7,user-agent仍旧保持同样模式。
需要注意的是,IE8对user-agent做了些微的改变,增加了渲染引擎,Trident/Version:Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
关于Windows NT 5.1 代表什么--》Microsoft Windows XP (Windows NT 5.1) (2001)
增加渲染引擎信息非常重要,因为当IE8以兼容模式运行,而渲染引擎版本保持不变时,MSIE的版本会变成7.0。也是因为原始的IE7的user-agent没有包含Trident版本,你可以在兼容模式浏览下,轻易的区分IE7和IE8。
注意:目前还不清楚,随着IE继续发展,Mozilla版本会永远不改变,因为这有点意思(user-agent不能绝对可靠的判定任何事情)
Gecko (壁虎)
Gecko渲染引擎是Firefox的核心。Gecko发展之初,它被当做典型Mozilla浏览器(后来的网景浏览器6)的一部分。同时,为网景浏览器6制定了一份说明书,说明在未来版本中user-agent的展现规格。新的格式相对于在4.x版本中使用的简单格式有相当大的改动, 有点背道而驰。新的格式如下:
Mozilla/MozillaVersion (Platform; Encryption; OS-or-CPU; Language; PrereleaseVersion[预先版本])Gecko/GeckoVersion ApplicationProduct/ApplicationProductVersion
这个非常复杂的User-agent融入了很多想法。为了更好的理解Gecko User-agent,琢磨一下以下从多种Gecko-base浏览器中获取的User-agent
运行在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.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
所有这些user-agent都表明浏览器是基于Gecko渲染引擎(虽然版本不同)。通常情况下,为了寻找一款特殊浏览器,了解其是否基于Gecko渲染引擎不是一项重要指标。自从第一款基于Gecko的浏览器发布后,Mozilla版本为5.0就没有更变过,看起来以后也不会变。
WebKit
2003年,苹果公司发布通告要发布自己的web浏览器,称为Safari。Safari的渲染引擎就是WebKit,WebKit起初作为KHTML格式渲染引擎的一个分支使用在基于Linux基准的web浏览器Konqueror中。几年后,WebKit脱离出来,建立了自己的开源项目,专注发展开源引擎。
这款新浏览器Safari和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
正如你所见,这是另一个长长的user-agent字符串。他新增了两个名目:Apple WebKit 版本和 Safari 版本。和那些基于Gecko标准的浏览器一样,所有基于WebKit标准的浏览器都定义他们自己为Mozilla 5.0。Safari 浏览器会生成一个代表性的浏览器版本号,这个代表性的数字不必非要代表当前的发布版本。所以,即使Safari 1.25浏览器的User-agent中有125.1,并不是和发布版本号一一对应的。出于这个原因,Safari浏览器的User-agent在第三版发布的时候略有增强。在User-agent中用了真实的版本号信息:
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
在Safari的User-agent中,最先发布的1.0版本中增添的"KHTML ,like Gecko"是最有趣且最受争议的事情。苹果公司收到了很多来自开发者的反馈,他们提出这是在糊弄用户和服务器,使他们认为Safari浏览器是基于Gecko的(即使Mozilla/5.0不起作用的情况下)。苹果公司的回复类似当年微软的遭遇:苹果浏览器是为了兼容Mozilla,而且站点不应该将苹果浏览器用户拒之门外就是因为他们似乎使用了一个不被服务器支持的浏览器。
注意,这个改变只针对Safari,不针对WebKit,所以那些基于WebKit标准的浏览器没有这个改变。一般来讲,是否像Gecko,这是一种典型的鉴别是否是WebKit浏览器的方法,相比专门鉴别是否是Safari浏览器更有效。
Konqueror
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)
这里面的Konqueror版本号和KHTML版本号趋于一致,或者是一丁点差异,就像Konqueror 3.5 基于 KHTML 3.5.1渲染。
Chrome
谷歌的Chrome浏览器采用WebKit作为他们得渲染引擎,但用的是不同的Javascript引擎。Chrome 0.2作为最初的beta发布版本, 它的User-agent在继承WebKit版本浏览器的格式的基础上,额外的加入了Chrome的版本信息。它的格式如下:
Mozilla/5.0 (Platform; Encryption; OS-or-CPU; Language) AppleWebKit/AppleWebKitVersion (KHTML, like Gecko) Chrome/ChromeVersion Safari/SafariVersion
整个Chrome 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
从这个User-agent可以看到,Webkit的版本和Safari的版本就像是一直在同步升级的,尽管这不可靠。
Opera
在user-agent被关心之前Opera一直是备受争议的浏览器。Opera的User-agent是在众多现代浏览器中最合理的,他正确的表明了自身身份和版本信息。截止8.0之前,它的user-agent的格式是这样的:
Opera/Version (OS-or-CPU; Encryption) [Language]
在Windows XP 电脑上运行的 Opera 7.54,它的User-agent格式是这样的:
Opera/7.54 (Window NT 5.1; U) [en]
伴随着Opera 8 的发布,为了更好的匹配其他浏览器,它将user-agent格式中末尾的语言部分移到了括号里面,就像这样:
Opera/8.0 (Windows NT 5.1; U; en)
默认情况下,Opera 回归了最原始的User-agent格式。当前情况下,opera是四个主流浏览器中唯一一个在User-agent中通过产品名和版本号来完整的表明自身身份的浏览器。然而,与其他浏览器比较,Opera在运用自身User-agent的过程中遇到了不少问题。虽然它的User-agent在技术上是正确的,然而在互联网上仍有一大堆在嗅探那些在User-agent中声明自己是Mozilla产品的浏览器的嗅探器代码。也有一定量的代码嗅探IE和Gecko浏览器。面对这种情况,Opera 通过改变自身user-agent格式将自己定义为完全不同的浏览器,来解决混乱的嗅探器带来的问题。
Opera 9 中有两种方法来改变User-agent字符串。一种是定义自己为另一个浏览器,无论是Firefox还是IE。当做了这种选择,User-agent看起来会像是和Firefox或者IE一样,同时在尾部增加了"Opera"和Opera的版本号。这里举个例子:
像Firefox:
Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50
像IE:
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50
第一个例子在保持Opera版本号的情况下将Opera 9.5伪装为Firefox 2。 第二个例子在保持Opera版本号的情况下将Opera 9.5伪装成为IE6。尽管以上这些User-agent可以经过Firefox和IE6的校验,同时保留了鉴别Opera的可能性。
另外一种方法就是完全将自己定义为Firefox或者是IE。当屏蔽浏览器身份的时候,返回的User-agent信息和伪装对象返回的user-agent信息完全一样-没有"Opera",没有任何关于Opera版本信息。在屏蔽浏览器身份的情况下,根本没有办法照着user-agent的字面意思去区分Opera和其他浏览器。Opera面对这个问题的深一层次的想法是在不通知用户的情况下,根据特定情况设定特殊的user-agent字符串,听起来更复杂化了。
结论
这段关于浏览器的User-agent的历史试图说明了user-agent其实什么都不是,它们很不可靠。
IE想要伪装成Netscape 4; Konqueror 和 WebKit 想要伪装成 Firefox; Chrome想要伪装成Safari。
尽管每个浏览器(包括Opera这个奇葩)为了让自己更出众,都给出了明确的信息让嗅探器探测到,但是这还是让user-agent嗅探变得越来越难。关于嗅探,你需要记住的是一个浏览器通过巨长的user-agent来欺骗你,那是因为他们相信自己的浏览器是兼容他们在user-agent中所提及运行环境。在这些情况下,甚至他们自己都不确定哪个是必须带的。
举个例子,Chrome要求索赔,因为那些能在Safari 3上运行的网站在Chrome上也能运行,所以应该没有必要去检测Chrome。这没有任何意义,无异于搬起石头砸自己的脚,所以现在Chrome恶搞Safari for Hotmail。Chrome并不是唯一一个做这样事情的,有很多由于浏览器兼容的引起的发生在幕后的事情。所以,战争仍在继续。
(原文出处:http://www.nczonline.net/blog/2010/01/12/history-of-the-user-agent-string/,初次翻译,请多指正,如有正解,请直言不讳的指出,谢谢)