检测浏览器是否使用“隐私浏览”模式

我正在build立一个公司关于安全的偏执狂的外联网。 他们希望确保(其中包括)用户浏览网站时,浏览器在浏览器中启用了“浏览私人浏览”模式,这样就不会保留cookie或历史logging。

我发现只有这个http://jeremiahgrossman.blogspot.com/2009/03/detecting-private-browsing-mode.html和https://serverfault.com/questions/18966/force-safari-to-operate-in-私人模式和检测,该状态-从-A-Web服务器

理想的解决scheme将使用没有或最小的JavaScript。 会尝试为所有浏览器和平台设置独特的Cookie工作吗? 任何人之前做过?

谢谢!


更新

http://crypto.stanford.edu/~collinj/research/incognito/使用其他海报提到的浏览器指纹机的CSS访问技术 – 感谢提示。

我喜欢它,因为它是小而优雅的,但仍然希望能够做到没有JavaScript,如果可能的话。

对于遇到此问题的其他人,请注意截至2014年,没有可靠的或准确的方式来检测是否有人通过Javascript或CSS以隐身/私密/安全浏览模式浏览。 以前曾经像CSS历史黑客那样工作的解决scheme已经被所有浏览器供应商无法使用。

永远不需要在正常的日常网站上检测隐私浏览模式的情况。 人们为了自己的理由select匿名浏览或不匿名浏览。

像Chrome和Firefox这样的浏览器不会再禁用像localStorage这样的function。 他们只是在一个临时位置命名空间,以防止使用它的网站错误。 一旦完成浏览,名称空间将被删除,并且不会保存任何内容。 如果您正在testinglocalStorage支持而不pipe模式如何,它将始终返回支持它的浏览器。

如果公司内部需要,您应该开发一个浏览器插件。 Chrome和Firefox尤其暴露内部API,允许插件检查用户是否处于隐私浏览/隐身模式,并相应地采取行动。 它不能在一个插件之外完成。

如果公司正在作出决定,而且这很重要,那么只要知道一些Javascript的开发者,一个插件就可以简单地检查你是否处于私密/隐身模式,并阻止你浏览直到开启。 然后你会问所有的公司雇员安装这个插件。

这是一个更简单的方法来检测隐私模式。 这只适用于Safari。 我创build它,因为我正在开发一个Web应用程序使用localStorage。 当处于隐私模式时,LocalStorage在Safari中不可用,因此我的应用程序将无法工作。 在页面加载时,运行下面的脚本。 如果我们不能使用localStorage,它会显示一个警告框。

 try { // try to use localStorage localStorage.test = 2; } catch (e) { // there was an error so... alert('You are in Privacy Mode\nPlease deactivate Privacy Mode and then reload the page.'); } 

这是我的探测私人模式

 function detectPrivateMode(cb) { var db, on = cb.bind(null, true), off = cb.bind(null, false) function tryls() { try { localStorage.length ? off() : (localStorage.x = 1, localStorage.removeItem("x"), off()); } catch (e) { // Safari only enables cookie in private mode // if cookie is disabled then all client side storage is disabled // if all client side storage is disabled, then there is no point // in using private mode navigator.cookieEnabled ? on() : off(); } } // Blink (chrome & opera) window.webkitRequestFileSystem ? webkitRequestFileSystem(0, 0, off, on) // FF : "MozAppearance" in document.documentElement.style ? (db = indexedDB.open("test"), db.onerror = on, db.onsuccess = off) // Safari : /constructor/i.test(window.HTMLElement) || window.safari ? tryls() // IE10+ & edge : !window.indexedDB && (window.PointerEvent || window.MSPointerEvent) ? on() // Rest : off() } detectPrivateMode(function (isPrivateMode) { console.log('is private mode: ' + isPrivateMode) }) 

您的网页无法确切地知道用户处于隐私浏览模式。 任何试图检查各种浏览器function的尝试都需要随着安全实现的更新而经常改变。 它可能会在一些浏览器中工作一段时间,但不是全部。

如果公司担心安全问题,我build议您将自己的Firefox或Chromium发行版locking隐私设置,并且只允许自定义客户端连接到外部networking。

可以为大多数使用的浏览器检测启用的隐私浏览模式。 这包括Safari,Firefox,IE10,Edge和Google Chrome。


火狐

当启用Firefox的隐私浏览模式时,IndexedDB将抛出一个InvalidStateError,因为它在隐私浏览模式下不可用。

如果是这样的话:

 var db = indexedDB.open("test"); db.onerror = function(){/*Firefox PB enabled*/}; db.onsuccess =function(){/*Not enabled*/}; 

苹果浏览器

对于Safari,关键是本地存储服务。 它在隐私模式下被禁用。 所以尝试访问它并使用try-catch子句。 以下方法适用于OSX和iOS设备。 这个方法的信用就是这个问题和答案

 var storage = window.sessionStorage; try { storage.setItem("someKeyHere", "test"); storage.removeItem("someKeyHere"); } catch (e) { if (e.code === DOMException.QUOTA_EXCEEDED_ERR && storage.length === 0) { //Private here } } 

IE10 /边缘

Internet Explore甚至会在隐私模式下禁用IndexedDB。 所以检查存在。 但这还不够,因为旧版浏览器可能甚至没有IDB。 所以做另一个检查,例如对于只有IE10和后续浏览器具有/触发的事件。 CodeReview的相关问题可以在这里find

 if(!window.indexedDB && (window.PointerEvent || window.MSPointerEvent)){ //Privacy Mode } 

Chromes隐身模式可以通过文件系统进行validation。 在这里可以find一个很好的解释

 var fs = window.RequestFileSystem || window.webkitRequestFileSystem; if (!fs) { console.log("FS check failed.."); return; } fs(window.TEMPORARY, 100, function (fs) {}, function (err) { //Incognito mode }); 

如果他们没有启用私人浏览,你不会阻止他们。

为什么有一个聪明的消息框呢?

会尝试为所有浏览器和平台设置独特的Cookie工作吗? 任何人之前做过?

我认为最优雅的解决scheme是:

  • 执行安全泄漏testing
  • 如果安全泄漏testing揭示问题
    • 告诉用户检查设置
    • build议隐私模式

因为正如你所说,不是每个人都可以或需要启用隐私模式。

隐私模式激活时,Web浏览器的行为会有所不同 。

在许多浏览器上,资源的caching是有限的。 可以根据CSScaching检测浏览器的位置 。 有可能在没有JavaScript的情况下进行这种攻击。

联邦军正在开展一项指纹浏览器项目。 隐私模式激活时,部分浏览器指纹将会有所不同。 来吧, 试试吧 。

我同意DigitalSeas的观点,我们通常不应该尝试检测用户是否处于“隐私浏览”模式。 不过,我最近发现,FireFox现在订阅了一个名为“disconnect.me”的服务,它提供了他们在“跟踪保护”function中使用的url黑名单。 由于disconnect.me列入某些社交networking(例如Facebook的facebook.net ),我们发现他们的SDK不会在FireFox中加载。 因此,为了向用户提供更有用,更准确的错误信息,我们可以尝试检测隐私浏览模式似乎是合理的。

有了这个理由, 这个要点声称提供检测隐私浏览主要浏览器使用特定于这些浏览器的技巧。 在写这篇文章的时候(这个要点可能在你阅读的时候已经更新了),检测逻辑如下:

 function retry(isDone, next) { var current_trial = 0, max_retry = 50, interval = 10, is_timeout = false; var id = window.setInterval( function() { if (isDone()) { window.clearInterval(id); next(is_timeout); } if (current_trial++ > max_retry) { window.clearInterval(id); is_timeout = true; next(is_timeout); } }, 10 ); } function isIE10OrLater(user_agent) { var ua = user_agent.toLowerCase(); if (ua.indexOf('msie') === 0 && ua.indexOf('trident') === 0) { return false; } var match = /(?:msie|rv:)\s?([\d\.]+)/.exec(ua); if (match && parseInt(match[1], 10) >= 10) { return true; } return false; } function detectPrivateMode(callback) { var is_private; if (window.webkitRequestFileSystem) { window.webkitRequestFileSystem( window.TEMPORARY, 1, function() { is_private = false; }, function(e) { console.log(e); is_private = true; } ); } else if (window.indexedDB && /Firefox/.test(window.navigator.userAgent)) { var db; try { db = window.indexedDB.open('test'); } catch(e) { is_private = true; } if (typeof is_private === 'undefined') { retry( function isDone() { return db.readyState === 'done' ? true : false; }, function next(is_timeout) { if (!is_timeout) { is_private = db.result ? false : true; } } ); } } else if (isIE10OrLater(window.navigator.userAgent)) { is_private = false; try { if (!window.indexedDB) { is_private = true; } } catch (e) { is_private = true; } } else if (window.localStorage && /Safari/.test(window.navigator.userAgent)) { try { window.localStorage.setItem('test', 1); } catch(e) { is_private = true; } if (typeof is_private === 'undefined') { is_private = false; window.localStorage.removeItem('test'); } } retry( function isDone() { return typeof is_private !== 'undefined' ? true : false; }, function next(is_timeout) { callback(is_private); } ); } 

localStorage技巧是一个已经修复的bug ,并且在Safari 11.0中不再适用。

在Safari,Opera和Internet Explorer(不是Chrome)中有一个有趣的select:那些浏览器发送一个DNT: 1标题(Do Not Track)。

这不是100%可靠的,因为这个头可以启用正常浏览(默认情况下是禁用),但它可以帮助识别隐私意识的用户。

那么,你不会真正将私人模式与“阻止所有cookies”区分开来,但除了这种罕见的情况之外,我想它应该起作用。


国际海事组织的一个大问题是,这是一个非常糟糕的网站devise,而不是比90年代常见的“你需要浏览器xxx来浏览这个网站”的好的网站。 并不是所有的浏览器都有一个专用浏览模式(就像我鄙视IE一样,例如切割IE7的用户),这些用户根本无法访问你的网站。

此外,当我在互联网上,我经常有多个网站打开多个选项卡。 如果只是为了看到该网站而不能同时访问其他网站,就不得不切换到私密模式,这实在令人烦恼。

你可以做的一件事就是使用会话而不是cookies来devise网站,所以它们不会被存储(因为你不使用它们)。 至于历史……真的,那有什么问题呢?

我已经通过使用两个HTML页面解决了这个问题。 主页面定义一个状态variables并设置一个cookie。 第二页在新窗口中打开(不是选项卡),读取cookie并将状态设置为cookie值。 在MSIE下,当主页处于正常模式时,cookie值被传递给子页面。 在InPrivate浏览模式下,cookie值不会传递给子页面(但是,如果您打开新的选项卡,则会传递该值)。

main.html页面:

 <script> var myCookie="nocookie"; document.cookie="checkInPrivate=1"; var h=window.open("child.html", "_blank", "left=9999,height=200,width=200"); setTimeout(function() { var status=null; if (myCookie=="nocookie") { status="unable to determine if we are InPrivate Browsing mode (child page did not set the cookie)"; } else if (myCookie.indexOf("checkInPrivate")>=0) { status="not in InPrivate Browsing mode (child page did set the cookie)"; } else { status="in InPrivate Browsing mode (child page set the cookie value but it was not provided)"; } alert(status); }, 200); </script> 

child.html页面:

 Detecting MSIE's InPrivate Browsing mode... <script> window.opener.myCookie=document.cookie; window.close(); </script> 

我使用的是InPrivate浏览模式,以防止浏览器助手对象(BHO)和浏览器扩展被启用,因为BHO通常是可以修改网页的恶意软件,即使使用HTTPS和强authentication也是如此。 Internet Explorer 9的“隐私”设置中有一个“InPrivate浏览开始时禁用工具栏和扩展名”。

但是,这不是防止恶意浏览器扩展的最终方法:恶意扩展可能会改变主页面行为,使其认为myCookie值尚未设置。 我们错误地认为我们处于InPrivate浏览模式。

请注意,我需要我的应用程序的Cookie,所以我不使用InPrivate浏览为此目的。

不知道是否它的原因这个问题是旧的,但Firefox确实提供了如何检测隐私浏览模式的文档。 但是它涉及到使用他们的DXR PrivateBrowsingUtils的导入:

 try { // Firefox 20+ Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); if (!PrivateBrowsingUtils.isWindowPrivate(window)) { ... } } catch(e) { // pre Firefox 20 (if you do not have access to a doc. // might use doc.hasAttribute("privatebrowsingmode") then instead) try { var inPrivateBrowsing = Components.classes["@mozilla.org/privatebrowsing;1"]. getService(Components.interfaces.nsIPrivateBrowsingService). privateBrowsingEnabled; if (!inPrivateBrowsing) { ... } } catch(e) { Components.utils.reportError(e); return; } } 

编写代码来实现以下

1)在Firefoxtesting浏览器版本。 此方法适用于版本> = 33.0(支持服务人员)。 旧式(<33.0)版本不能使用此方法。

2)尝试设置服务人员。 3)如果您可以设置,使用或访问服务工作者,则1000%不处于隐私浏览模式,因为服务人员不能在Firefox隐私浏览模式下进行交互。 我希望他们可以。

引用:

“在Firefox中,当用户处于隐私浏览模式时,Service Worker API是隐藏的,不能使用”

https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers