如何在不使用window.navigator的情况下可靠地检测浏览器?

21
我知道在Stack Overflow上有很多关于使用JavaScript检测浏览器的问题。我的问题是,如何在不使用window.navigator(包括navigator.userAgent)的情况下检测浏览器?
首先澄清一下,我不需要知道渲染引擎,这不是为了自适应布局,而且请不要惊慌:我已经进行了特性检测。如果“为什么”我要求检测浏览器很重要,请评论,我将很乐意加入解释,但这可能会使问题变得非常冗长。
接下来,让我说明为什么我的问题不是重复的:
  • 在Javascript中检测浏览器? 因为有19个答案,其中12个明确使用了navigator.userAgent(包括使用userAgent的jQuery.browser,但现已被删除),4个使用navigator.appName(在Chrome中会返回“Netscape”……),1个通过建议特征检测来回避问题,这与浏览器检测不同(我已经在使用特征检测,但为了知道它们的使用程度,我需要浏览器检测),2个并非真正的答案或只适用于IE。(尽管这个非答案实际上非常详细地解释了为什么我的问题很重要:我试图避免在某些浏览器上出现崩溃标签的痛点!)由于我的问题正在寻求一种不使用window.navigator的答案(即使是hack?),所以它不是那个问题的重复。

  • 如何检测用户是否在使用IE浏览器? 因为有11个答案,其中10个使用navigator.userAgent,而另一个则使用IE技巧仅检测IE,这不足以回答我的问题(尽管它可能是发布在此处的有用解决方案的一小部分)?

  • 在Javascript中,如何确定当前浏览器是否为Firefox(计算机上)而不是其他浏览器? 因为有11个答案,其中8个使用navigator.userAgent,2个建议特征检测(同样不是我的问题),而1个甚至不是一个真正的答案。

  • 如何检测Chrome和Safari浏览器(WebKit)? 因为有8个答案,其中6个使用navigator.userAgent,而2个则是针对WebKit的。不幸的是,WebKit不一定只与Safari相关,我需要知道的是浏览器,而不是渲染引擎。

希望这很清晰明了。
我知道还有其他方法可以做到这一点,但是我不太了解每个浏览器的内部情况。在某些浏览器中,是否有一些对象或变量始终或可靠地暴露给JavaScript呢?也许有吗?我知道一些实验性API是供应商前缀的,但这似乎不适用于商业产品,尽管如果需要,我愿意降低要求。还有其他可能性吗?

5
这是数百万其他更具体的问题的副本,例如https://dev59.com/fGcs5IYBdhLWcg3wu2Up和https://dev59.com/_HE95IYBdhLWcg3wadGq以及https://dev59.com/MGIj5IYBdhLWcg3wrG8q和https://dev59.com/uXE95IYBdhLWcg3wOLU1。 - user229044
7
@meager,你真的读了我的问题吗?除了用户代理之外,浏览器类型还可以被检测出哪些方式?请重新开放这个问题。 - Matt
3
所有这些问题都有非UA的答案。 - user229044
4
在这里,window.navigator实际上被视为用户代理字符串,但我正在努力避免使用它。 - Matt
2
那么,为什么不运行一些示例JavaScript来实际估计性能,而不仅仅提供预定义的估计值呢?你提出的方法可能经不起时间的考验。这还没有考虑你将忽略的浏览器版本之间的差异,例如Firefox ESR版本、Chrome Stable/Canary以及像Midori这样你没有考虑到的浏览器和根本不是浏览器的脚本引擎,如nodejs/V8。 - Goyuix
显示剩余12条评论
2个回答

7

一个想法:

  • IE使用ActiveX(仍然在IE11中,遗留),您可以通过查看ActiveX可用性相当容易地推断出用户正在使用IE,但是如果安全设置打开,您需要回退到其他功能检测。
  • Chrome和Firefox都支持扩展的使用,也许检测这些扩展将有所帮助
  • Chrome在全局范围内提供了window['chrome']['webstore']对象。
  • 您可以使用Object.keys对窗口对象进行排序,并查找供应商特定名称,例如'moz''ms''o'

如果结合moz、ms和chrome-object,您就可以嗅探出三个最大的浏览器。

顺便说一下,功能检测仍然是最佳选项,不是针对OP,而是针对那些“我刚刚开始编程,我想知道如何嗅探浏览器程序员”的人。


2
是的! 这就是我在寻找的那种技巧!谢谢。 我会尝试这些想法。 - Matt

6

首先,要明确的是,没有任何入站HTTP请求能够保证准确地说明他们是谁。事实上,一些黑客通过伪造HTTP头文件中的User-Agent字段来操作。大多数浏览器提供商通过在入站HTTP请求头的User-agent字段中声明自己的方式来很好地识别自己。在Javascript层工作的唯一问题是它比查看头文件的层次高了一层。不过,有一些技巧,下面是其中之一:

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
alert(headers);

在思考了一段时间并且对网络方面非常了解后,我找到了这个答案... 你可以在这里阅读更多信息:JavaScript中访问网页的HTTP头,实际上这个问题可以被认为是那个答案的一个副本,但并不是每个人都知道HTTP层。上面的代码假装是一个合法的入站请求,并使用“Get”打开document.location,但没有发送任何内容。不知道浏览器内部工作原理,我猜想是DOM本身返回了已知的头信息。只需解析响应的User-Agent部分即可完成所有设置。


2
你说得对,User-Agent 不是检测浏览器可靠的方法之一;这也是我想要避免使用它的原因之一。(参见 http://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx)不过,你提出的解决方案真的很聪明,我从来没有想到过! - Matt
感谢您发布链接,我之前看到过“Edge”这个东西,但一直不知道它是什么(直到现在)。祝您在寻找解决方案的过程中好运。 - JWP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接