iOS 12 Safari 的隐私/隐身模式检测

Posted

技术标签:

【中文标题】iOS 12 Safari 的隐私/隐身模式检测【英文标题】:Private / Incognito Mode Detection for iOS 12 Safari 【发布时间】:2019-03-16 11:42:02 【问题描述】:

似乎适用于 ios 11 和相应 Safari 版本的旧检测方法不再适用。 我试过这个脚本:https://gist.github.com/cou929/7973956 但它不适用于 iOS 12 上的 safari,也不适用于 iOS 12 上的 Chrome 69。

这个全新的库也不适用于 iOS 12 浏览器:https://github.com/Maykonn/js-detect-incognito-private-browsing-paywall

那么 iOS 12 浏览器有什么解决方案吗?

BostonGlobe 似乎有一个解决方案,但我不知道他们是如何做到的:https://www.bostonglobe.com/sports/redsox/2018/10/09/redsox/D66J59viZ1qxyZlhI18l8L/story.html (如果你想在隐身/私人模式下阅读 BostonGlobe.com 的文章,你会看到一个要求你登录的屏幕)

【问题讨论】:

If you want to read an BostonGlobe.com article in incognito / private mode you get a screen which asks you to log in,当你打开一个需要你登录的网站时,在隐身状态下,你必须重新登录,这并不一定表明该网站使用incognito detection @AlexanderSolonik 试试吧。如果您未处于隐身模式 - 您可以阅读文章;在隐身模式下,您会被要求登录,它甚至会告诉您它检测到您的浏览器处于隐身模式 【参考方案1】:

Chrome Devtools => 检测隐身/隐私模式的模块名为“detect-private-browsing”,位于webpack:///./~/detect-private-browsing/index.js

// ./~/detect-private-browsing/index.js

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;
    
    // MS Edge Detection from this gist: https://gist.github.com/cou929/7973956
    var edge = /edge/.exec(ua); 
    if (edge && edge[0] == "edge")  
        return true; 
    
    return false;


module.exports = 
    detectPrivateMode: function(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)) 

            // One-off check for weird sports 2.0 polyfill
            // This also impacts iOS Firefox and Chrome (newer versions), apparently
            // @see bglobe-js/containers/App.js:116
            if (window.safariIncognito) 
                is_private = true;
             else 
                        try 
                           window.openDatabase(null, null, null, null);
                         catch (e) 
                           is_private = true;
                        

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

【讨论】:

不,抱歉 - 我不明白。这是webpack:// 链接?你从哪里得到的? 是的。从 Chrome 的 DevTools 调试网站,因为它使用 webpack 进行捆绑。 哇,就是这样。它正在工作!我只是通过删除module.exports = 包装器并使detectPrivateMode 成为正常功能,将其更改为本机javascript。唯一的问题是——我仍然无法通过我的 Chrome DevTools 找到这段代码——你能解释一下你是如何找到它的吗?非常感谢! 有趣的是,BostonGlobe 似乎使用了我在问题中提到的一个脚本的修改:gist.github.com/cou929/7973956 好的,刚刚知道如何在 DevTools > Sources > Page 中搜索文件:使用快捷键 Ctrl + P (***.com/a/42024808/3391783)【参考方案2】:
//FOR IOS 12
var e = false;
if (window.localStorage && /Safari/.test(window.navigator.userAgent)) 
  if (window.safariIncognito) 
    e = true;
   else 
    try 
      window.openDatabase(null, null, null, null);
      window.localStorage.setItem("test", 1)
     catch (t) 
      e = true;
      alert("PRIVATE");
    
  
  void !e && (e = !1, window.localStorage.removeItem("test"))

【讨论】:

请在答案中添加一些细节,例如这段代码将如何解决问题以及它的作用......它使答案更有帮助 这在 safari 上运行良好。上面接受的答案没有

以上是关于iOS 12 Safari 的隐私/隐身模式检测的主要内容,如果未能解决你的问题,请参考以下文章

让用户在浏览时使用隐身模式而不是正常浏览

UIWebView 和 sessionStorage 中的隐私浏览模式

iOS Safari阅读模式研究

iOS Safari 隐私浏览 localStorage 和 sessionStorage 支持?

iOS Safari 未从第一次呈现完整页面

如何在隐身模式下启用Chrome扩展程序?