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

IT技术 javascript html security browser cookies
2021-01-23 09:41:40

我正在为一家对安全有疑虑的公司建立一个外联网。他们希望确保(除其他外)他们的用户在浏览器的隐私浏览模式下浏览网站,这样就不会保留任何 cookie 或历史记录。

我只发现了这个 http://jeremiahgrossman.blogspot.com/2009/03/detecting-private-browsing-mode.htmlhttps://serverfault.com/questions/18966/force-safari-to-operate-in-私有模式并检测来自网络服务器的状态

理想的解决方案是不使用或最少使用 javascript。尝试为所有浏览器和平台设置唯一的 cookie 是否可行?以前有人做过这个吗?

谢谢!


更新

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

我喜欢它,因为它小巧而优雅,但如果可能的话,仍然希望能够在没有 javascript 的情况下完成它。

6个回答

2019 年 6 月更新

谷歌正在移除在 Chrome 76 及更高版本中永久检测隐私浏览模式的功能。所以,如果你想检测隐私浏览,现在是不可能的(除非你找到了一种谷歌没有找到的方法)。检测隐私浏览模式的能力已被认为是一个错误,并且从未打算过。

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

永远不应该出现需要在正常的日常网站上检测隐私浏览模式的情况。人们出于自己的原因选择匿名浏览或不匿名浏览。

Chrome 和 Firefox 等浏览器不再禁用 localStorage 等功能。他们只是将它命名为一个临时位置,以防止使用它的网站出错。完成浏览后,命名空间将被删除,并且不会保存任何内容。如果您正在测试 localStorage 支持,而不管模式如何,对于支持它的浏览器,它将始终返回 true。

其他在 Chrome 中检测私有模式的方法已被完全修补,将不再有效。

如果公司内部需要,你应该开发一个浏览器插件。特别是 Chrome 和 Firefox,公开了内部 API,允许插件检查用户是否处于隐私浏览/隐身模式和相应的操作。它不能在插件之外完成。

There should never be a situation where needing to detect private browsing mode 不完全正确,Apple 存在问题:stackoverflow.com/questions/21159301/...最好通知客户端它不会在私有模式下工作。
2021-03-16 09:41:40
“永远不应该出现需要在正常的日常网站上检测隐私浏览模式的情况” - 实际上,这是一个。我们正在开发一个网站,为针对妇女的暴力行为提供资源。作为该网站的一部分,我们希望让未以私密模式浏览的用户了解他们需要使用私密模式来确保网站访问不在他们的历史记录中。我想检测用户是否未处于私密模式,如果是这种情况,请提供有关如何清除最近的缓存并以私密模式返回的适当说明。
2021-03-16 09:41:40
哦,还有情况下,相信我。例如,WordPress 会存储您是否在 cookie 中登录。当您关闭私人模式选项卡或窗口时,这些会被破坏。在当前的一个案例中,我们遇到的问题是人们不断抱怨他们必须一遍又一遍地登录,因为Safari私有模式基本窗口没有解释 Cookie 会发生什么。他们只是认为“历史没有被保存”,并相信这将有助于保持他们的隐私。
2021-03-19 09:41:40
纽约时报现在正在他们的网站上实施此验证,并要求您登录或创建一个帐户。以前(大约一周前)如果您达到“免费文章”限制,您可以在隐身模式下加载网站并阅读您想要的所有内容。我猜他们抓住了!它也反驳了您的说法,即从来没有检测隐私浏览模式的用例。
2021-03-24 09:41:40
我们有多个用户没有意识到他们处于隐私浏览模式,并认为我们的网站存在问题。我完全不同意你的假设,即永远不需要检测到这一点。
2021-03-25 09:41:40

这是检测隐私模式的更简单方法。这仅适用于 Safari。我创建它是因为我正在开发的 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.');
}
也许还添加 localStorage.test = null; 所以它不会污染其他浏览器的存储?
2021-03-13 09:41:40
@PaulAnnekov 是的,如答案中所述,这只适用于 Safari 浏览器
2021-03-21 09:41:40
@ChrisWren 每个浏览器都有自己的本地存储。他们不分享。
2021-03-22 09:41:40
谢谢,这解释了一些网站如何检测到这一点。我发现一个网站可以解决这个问题非常令人毛骨悚然......(注意这是在 Firefox 55 中。)
2021-03-22 09:41:40
这只是由于 Safari 中的一个错误才有可能,该错误已从 iOS 11 开始修复
2021-03-29 09:41:40

当前状态

谷歌浏览器进一步发展,在使用隐身模式时没有更多的检测空间。同样可能适用于其他浏览器。


旧解决方案(可能部分有效)

可以为大多数使用的浏览器检测启用的隐私浏览模式。这包括 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 Explorer 甚至会在隐私模式下禁用 IndexedDB。所以检查是否存在。但这还不够,因为较旧的浏览器可能甚至没有 IDB。所以再做一次检查,例如对于只有 IE10 和后续浏览器具有/触发的事件。可以在此处找到有关 CodeReview 的相关问题

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

铬合金

更新:自 Chrome 76 起这不起作用(感谢 @jLynx)

Chromes 隐身模式可以通过文件系统进行验证。一个很好的解释可以在这里找到SO

var fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) {
    console.log("FS check failed..");
    return;
}

fs(window.TEMPORARY, 100, function (fs) {}, function (err) {
//Incognito mode
});
Safari 不再对我有用(11.1.2),但引用的 SO 问题得到了一个新答案,这对我有用stackoverflow.com/a/47642304/333864
2021-03-13 09:41:40
纽约时报网站可以检测到以隐身模式运行的 Chrome 80,因此除此之外还有其他功能。
2021-03-14 09:41:40
Vanity Fair 会检测 Chrome Incognito 和 Firefox Privacy 模式。您选择了一篇文章并开始滚动,几秒钟后它会弹出“您处于隐私模式,停止它”味精。
2021-03-17 09:41:40
Edge 检查不再有效,因为 window.indexedDB 现在也以私有模式存在。
2021-03-21 09:41:40

Chrome 83 带来了重新设计的安全设置,默认情况下在隐身模式中阻止了第三方 cookie!

所以这很容易,创建一个 iframe 到第三方站点,让它发postMessage回通知你navigator.cookieEnabled是真的还是假的。Ofc 用户也可以选择禁用第三方 cookie。所以我在设置中测试并禁用了第 3 方 cookie。但它仍然说在第三方 iframe 上启用了 cookie 使用navigator.cookieEnabled. 只有在我使用隐身模式后它才被禁用 - 也许是一个错误?

new Promise((rs, rj, m = new MessageChannel(), d = document, i = d.createElement('iframe')) => {
  i.src = 'https://httpbin.org/base64/PHNjcmlwdD5vbm1lc3NhZ2UgPSBlID0+IGUuZGF0YS5wb3N0TWVzc2FnZShuYXZpZ2F0b3IuY29va2llRW5hYmxlZCk8L3NjcmlwdD4='
  i.onload = _ => i.contentWindow.postMessage(m.port1, '*', [m.port1], m.port2.onmessage = e => i.remove(rs(e.data)))
  i.hidden = 1
  d.body.append(i)
}).then(thirdPartyCookieEabled => 
  console.log('Third party cookie enabled:', thirdPartyCookieEabled)
)

您也可以仅使用 js + ajax 来完成它,但不想设置 2 个服务器来自己测试它。但是对于这个 SameSite=none 也必须设置。

res = await fetch('https://httpbin.org/cookies/set?enabled=1', {
  credentials: 'include' 
})
json = await res.json()
console.log(!!json.cookies.enabled)

这是我对检测私人模式的看法

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)
})

编辑发现了一种现代的、更快的、synkronas 方式在 firefox 中尝试它(他们没有在私有模式下的服务工作者)类似于 ie 不包括 indexedDB 但该测试仅适用于安全站点

: "MozAppearance" in document.documentElement.style ? navigator.serviceWorker ? off() : on()
2021-04-11 09:41:40
注意:在 IE10 或 11 中不原生支持 Promise。我假设你在这里使用了 polyfill? caniuse.com/#search=promise
2021-04-12 09:41:40
@kevinDice 我把它改成了一个简单的回调
2021-04-12 09:41:40

您的网页无法绝对肯定地知道用户处于隐私浏览模式。随着安全实施的更新,任何检查各种浏览器功能的尝试都需要经常更改。它可能在某些浏览器中工作一段时间,但不是全部。

如果公司担心安全性,我建议您使用锁定的隐私设置滚动您自己的 Firefox 或 Chromium 发行版,并且只允许该自定义客户端连接到外联网。

嗯...我自己的跨平台 FF 发行版?这有点费劲……您知道 80% 的解决方案吗?(例如,80% 的时间我们可以猜测用户是否处于隐私浏览模式)。我希望为访问者提供一些安全建议:使用隐私浏览就是其中之一。正如其他人所建议的那样,并非所有访客都愿意这样做,而且其中可能有 1/4 的人会在“安全”的地方并且不需要。
2021-03-14 09:41:40
有什么佐证?不告诉你隐私浏览是否开启的“指纹”?该公司“对安全性偏执”,因此仅靠所谓的指纹是不够的。
2021-03-27 09:41:40
推荐不需要知道用户是否正在执行该建议。
2021-03-30 09:41:40
-1 OP 说这不是解决方案“我的 10% 的用户将通过非常脆弱的 24k 拨号线路登录,并且如果他们幸运的话,每天只有几个小时的电”
2021-04-01 09:41:40