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

Javascript 检测浏览器是否使用私有浏览模式,javascript,html,security,browser,cookies,Javascript,Html,Security,Browser,Cookies,我正在为一家对安全性有疑心的公司建立一个外联网。他们希望确保(除其他外)他们的用户在其web浏览器中打开私人浏览模式的情况下浏览网站,这样就不会保留cookie或历史记录 我只找到了这个 和 理想的解决方案是不使用或使用最少的javascript。尝试为所有浏览器和平台设置唯一的cookie是否有效?以前有人这样做过吗 谢谢 更新 使用其他海报提到的浏览器指纹的CSS访问技术-谢谢提示 我喜欢它,因为它小巧优雅,但如果可能的话,我仍然希望能够在不使用javascript的情况下使用它 您的网

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

我只找到了这个 和

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

谢谢


更新

使用其他海报提到的浏览器指纹的CSS访问技术-谢谢提示


我喜欢它,因为它小巧优雅,但如果可能的话,我仍然希望能够在不使用javascript的情况下使用它

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


如果公司如此关注安全性,我建议您使用锁定隐私设置的Firefox或Chromium发行版,只允许自定义客户端连接到外联网。

好吧,这样您就无法真正区分私有模式和“阻止所有cookie”,但除了这种罕见的情况,我想它应该会起作用


在我看来,最大的问题是,这是一个非常糟糕的网站设计,并不比90年代常见的好ol“你需要浏览器xxx才能看到这个网站”要好。并不是所有的浏览器都有一个私人浏览模式(就像我鄙视IE一样,比如你删掉了IE7用户),这些用户根本无法访问你的网站

此外,当我在互联网上,我经常有几个标签打开多个网站。这将是真的很烦人,我不得不切换到私人模式只是为了看到该网站,而不能访问其他网站在同一时间

您可以做的一件事是使用会话而不是cookie来设计站点,这样它们就不会被存储(因为您不使用它们…)。至于历史。。。真的,这有什么问题吗?

当隐私模式被激活时,网络浏览器

在许多浏览器上,资源的缓存是有限的。可以根据CSS缓存进行检测。有可能发动这次袭击


EFF正在进行一个项目,目的是:。当隐私模式被激活时,浏览器指纹的某些部分将不同。去吧

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

为什么要有一个智能消息框呢

尝试为所有浏览器和平台设置唯一的cookie是否有效?以前有人这样做过吗

我认为最优雅的解决方案是:

  • 执行安全泄漏测试
  • 如果安全泄漏测试发现问题
    • 告诉用户检查设置
    • 建议隐私模式

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

我通过使用两个HTML页面解决了这个问题。主页面定义状态变量并设置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>
Detecting MSIE's InPrivate Browsing mode...
<script>
window.opener.myCookie=document.cookie;
window.close();
</script>
我使用InPrivate浏览模式是为了防止启用浏览器助手对象(BHO)和浏览器扩展,因为BHO通常是恶意软件,即使使用HTTPS和强身份验证,也可以修改网页。Internet Explorer 9的“隐私”设置中有一个“当InPrivate浏览开始时禁用工具栏和扩展”

但是,这并不是防止恶意浏览器扩展的最终方法:恶意扩展可能会更改主页行为,使其认为未设置并删除
mycokie
值。我们会错误地认为我们处于非私有浏览模式


请注意,我的应用程序需要cookies,因此我不使用InPrivate浏览来实现此目的。

这里有一个更简单的方法来检测隐私模式。这只适用于Safari。我创建它是因为我正在开发的一个web应用程序使用本地存储。当Safari处于隐私模式时,LocalStorage不可用,因此我的应用程序将无法工作。 在页面加载时,运行下面的脚本。如果我们不能使用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.');
}

2019年6月更新

谷歌将在Chrome76以后的版本中永久检测私人浏览模式。所以,如果你想检测私人浏览,现在是不可能的(除非你找到一种谷歌没有找到的方法)。检测私人浏览模式的能力已被确认为一个bug,而且从来没有打算这样做

对于遇到这个问题的其他人,请注意,截至2014年,没有可靠或准确的方法来检测是否有人通过Javascript或CSS以匿名/私人/安全浏览模式浏览。以前的解决方案曾经像CSS历史黑客一样工作,但现在所有浏览器供应商都无法使用


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

Chrome和Firefox等浏览器不再禁用localStorage等功能。他们只是在一个临时位置命名它,以防止使用它的网站出错。完成浏览后,名称空间将被擦除,而不会保存任何内容。如果您正在测试本地存储支持,而不考虑模式,那么对于支持本地存储的浏览器,它将始终返回true
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);
        }
    );
}
var db = indexedDB.open("test");
db.onerror = function(){/*Firefox PB enabled*/};
db.onsuccess =function(){/*Not enabled*/};
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
    }
}
if(!window.indexedDB && (window.PointerEvent || window.MSPointerEvent)){
 //Privacy Mode
}
var fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) {
    console.log("FS check failed..");
    return;
}

fs(window.TEMPORARY, 100, function (fs) {}, function (err) {
//Incognito mode
});
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;
      }
    }
isPrivateWindow(function(is_private) {
    if(is_private)
        alert('Private');
    else
        alert('Not Private');
});
function isPrivate(callback) {
  callback || (callback = function(){});
  var fs = window.RequestFileSystem || window.webkitRequestFileSystem;

  if(fs){
    return fs(window.TEMPORARY, 1, callback.bind(this, false), callback.bind(this, true));
  }

  if(window.indexedDB && /Firefox/.test(window.navigator.userAgent)){
    try {
      var db       = window.indexedDB.open('test');
      var tryes    = 0;
      var interval = limit = 10;

      var wait = function(check){
        if(tryes >= limit){ return callback(true); } // Give up
        return window.setTimeout(check, ++tryes * interval);
      }

      var evaluate = function(){
        return db.readyState === 'done' ? callback(!db.result) : wait(evaluate);
      }

      return wait(evaluate);
    } catch (e) {
      return callback(true);
    }
  }

  if (!!window.navigator.userAgent.match(/(MSIE|Trident|Edge)/)){
    try {
      return callback(!window.indexedDB);
    } catch (e) {
      return callback(true);
    }
  }

  try {
    window.openDatabase(null, null, null, null);
    return callback(false);
  } catch (e) {
    return callback(true);
  }
}

isPrivate( function(isPrivate) {
  console.log('Private mode ===>', isPrivate);
});