Javascript 检查是否启用了第三方cookie

Javascript 检查是否启用了第三方cookie,javascript,cookies,Javascript,Cookies,我有一个应用程序需要检查客户端浏览器是否启用了第三方cookie。有人知道如何在JavaScript中实现这一点吗?理论上,你只需要在某个地方调用一个页面,设置第三方cookie,然后检查cookie是否存在。但是,标准浏览器安全性不允许来自域A的脚本对域B、C等上设置的cookie执行任何操作。。。e、 g.您无法访问“外来”cookies 如果您考虑了一些特定的用法,例如检查广告是否被阻止(这也会阻止第三方跟踪cookie),您可以检查广告服务器的内容是否在页面的DOM中,但您看不到cook

我有一个应用程序需要检查客户端浏览器是否启用了第三方cookie。有人知道如何在JavaScript中实现这一点吗?

理论上,你只需要在某个地方调用一个页面,设置第三方cookie,然后检查cookie是否存在。但是,标准浏览器安全性不允许来自域A的脚本对域B、C等上设置的cookie执行任何操作。。。e、 g.您无法访问“外来”cookies

如果您考虑了一些特定的用法,例如检查广告是否被阻止(这也会阻止第三方跟踪cookie),您可以检查广告服务器的内容是否在页面的DOM中,但您看不到cookie是否在那里。

技术背景 第三方通过HTTP(非JavaScript)设置和读取cookie

因此,我们需要向外部域发出两个请求,以测试是否启用了第三方cookie:

  • 第三方设置cookie的一个或多个
  • 第二种,根据浏览器是否在第二次请求中将cookie发送回同一第三方,响应不同
  • 由于DOM安全模型,我们不能使用XMLHTTPRequest(Ajax)

    显然,您不能同时加载这两个脚本,或者第二个请求可能在第一个请求的响应返回之前发出,并且测试cookie不会被设置

    代码示例 鉴于:

  • .html
    文件位于一个域中,并且

  • .js.php
    文件位于第二个域中,我们有:

  • HTML测试页面 另存为
    第三方cookies.html

    <!DOCTYPE html>
    <html>
    <head id="head">
      <meta charset=utf-8 />
      <title>Test if Third-Party Cookies are Enabled</title>
    <style type="text/css">
    body {
      color: black;
      background: white none;
    }
    .error {
      color: #c00;
    }
    .loading {
      color: #888;
    }
    .hidden {
      display: none;
    }
    </style>
    <script type="text/javascript">
    window._3rd_party_test_step1_loaded = function(){
      // At this point, a third-party domain has now attempted to set a cookie (if all went to plan!)
      var step2Url = 'http://third-party.example.com/step2.js.php',
        resultsEl = document.getElementById('3rd_party_cookie_test_results'),
        step2El = document.createElement('script');
    
      // Update loading / results message
      resultsEl.innerHTML = 'Stage one complete, loading stage 2&hellip;';
      // And load the second part of the test (reading the cookie)
      step2El.setAttribute('src', step2Url);
      resultsEl.appendChild(step2El);
    }
    window._3rd_party_test_step2_loaded = function(cookieSuccess){
      var resultsEl = document.getElementById('3rd_party_cookie_test_results'),
        errorEl = document.getElementById('3rd_party_cookie_test_error');
      // Show message
      resultsEl.innerHTML = (cookieSuccess ? 'Third party cookies are <b>functioning</b> in your browser.' : 'Third party cookies appear to be <b>disabled</b>.');
    
      // Done, so remove loading class
      resultsEl.className = resultsEl.className.replace(/\bloading\b/,' ');
      // And remove error message
      errorEl.className = 'hidden';
    }
    </script>
    </head>
    <body id="thebody">
    
      <h1>Test if Third-Party Cookies are Enabled</h1>
    
      <p id="3rd_party_cookie_test_results" class='loading'>Testing&hellip;</p>
      <p id="3rd_party_cookie_test_error" class="error hidden">(If this message persists, the test could not be completed; we could not reach the third-party to test, or another error occurred.)</p>
    
      <script type="text/javascript">
      window.setTimeout(function(){
        var errorEl = document.getElementById('3rd_party_cookie_test_error');
        if(errorEl.className.match(/\berror\b/)) {
          // Show error message
          errorEl.className = errorEl.className.replace(/\bhidden\b/,' ');
        } else {
        }
      }, 7*1000); // 7 sec timeout
      </script>
      <script type="text/javascript" src="http://third-party.example.com/step1.js.php"></script>
    </body>
    </html>
    
    第二个第三方JavaScript文件 另存为
    step2.js.php

    这是用PHP编写的,因此我们可以在响应之前读取服务器端的cookies。我们还清除cookie,以便可以重复测试(如果您想干扰浏览器设置并重试)

    
    窗口。第三方测试步骤2加载();
    
    最后一行使用三元运算符输出文字Javascript
    true
    false
    ,具体取决于测试cookie是否存在

    . 可供您随时进行测试

    (作为最后一点-不要在未经他人许可的情况下使用他人的服务器来测试第三方Cookie。它可能会自发破坏或注入恶意软件。这很粗鲁。)

    很好,但您不必使用PHP或任何其他服务器端编程语言

    至少如果您使用nginx:)

    这是Alan解决方案的纯*nginx服务器端配置:

    # Nginx config start
    server {
      listen 80;
      server_name third-party.example.com
      
      # don't allow user's browser to cache these replies
      expires -1;
      add_header Cache-Control "private";
      etag off;
      
      # The first third-party "JavaScript file" - served by nginx
      location = /step1.js.php {
        add_header Content-Type 'application/javascript; charset=UTF-8';
        
        add_header Set-Cookie "third_party_c_t=hey there!;Max-Age=172800";
        
        return 200 'window._3rd_party_test_step1_loaded();';
      }
      
      # The second third-party "JavaScript file" - served by nginx
      location = /step2.js.php {
        add_header Content-Type 'application/javascript; charset=UTF-8';
        
        set $test 'false';
        if ($cookie_third_party_c_t = 'hey there!') {
          set $test 'true';
          # clear the cookie
          add_header Set-Cookie "third_party_c_t=;expires=Thu, 01 Jan 1970 00:00:00 GMT";
        }
        
        return 200 'window._3rd_party_test_step2_loaded($test);';
      }
      
      # Nginx config end
    }
    

    旁注:

    • 是的,是的,我知道
    • 为了与Alan的“HTML测试页面”(
      third party cookies.HTML
      )完全兼容,我保留了以“.php”结尾的名称
    • 您还可以将两个位置的公共“设置内容类型标题”行移动到配置的
      服务器
      部分(范围)-我将其保留为保留更多“1:1”翻译

      • 这里有一个纯JS解决方案,不需要任何服务器端代码,因此它可以从静态CDN工作:-第一个脚本在代码中设置cookie,然后重定向到第二个脚本,该脚本将向父窗口发布消息

        您可以使用试用live版本。
        请注意,此演示似乎不再有效。可能正在阻止
        窗口.postMessage
        调用

        客户端HTML:

        third party cookies are <span id="result"/>
        <iframe src="https://mindmup.github.io/3rdpartycookiecheck/start.html"
            style="display:none" />
        
        当然,这需要客户端运行JavaScript,这与基于服务器的解决方案相比是一个缺点;另一方面,它更简单,您询问的是JS解决方案

        通过URL白名单检测第三方Cookie

        &对于大多数用例来说已经足够好了,但是如果您希望您的用户只对某些域执行第三方cookie的白名单,那么这些解决方案将不起作用

        我正在介绍一个稍微修改过的版本

        为此,我们需要两个域:

        • 域1,这是您的用户登陆的页面,它最初设置
          tpc=pending
          ,然后重定向到域2
        • 域2在iFrame中注入域1的url,尝试设置cookie
          tpc=true
          ,并重定向回域1
        • 现在,域1读取cookie
          tpc
          并检查其
          true
          ,如果我们得到的值为true,则允许第三方cookie,如果它仍然处于
          挂起状态
          第三方cookie被阻止
        现在,您可以要求您的用户仅为
        域1
        列出白名单(允许第三方cookie)
        ,而且通过这种技术,如果用户已将您的域列入白名单,则第三方检测将是准确的


        这是测试铬74,75,76和边缘78

        不幸的是,Mozilla不像Chrome那样提供URL的白名单,Safari也有自己的检测第三方cookie(ITP)的机制


        p.S.将在我有时间时在我的github中上载此演示。

        我的解决方案是从设置cookie的外部域加载,检查是否成功,然后将结果(1或0)作为参数传递给回调函数

        HTML:

        <script>
        function myCallback(is_enabled) {
            if (is_enabled===1) {//third party cookies are enabled
            }
        }
        </script>
        <script src="https://third-party-domain/third-party-cookies.php?callback=myCallback"></script>
        
        
        函数myCallback(已启用){
        如果(is_enabled==1){//第三方cookie已启用
        }
        }
        
        如果您喜欢异步运行,可以使用async和defer属性

        这也适用于jQuery:

        <script>
        $.ajax({
            url: 'https://third-party-domain/third-party-cookies.php',
            dataType: 'jsonp',
        }).done(function(is_enabled) {
            if (is_enabled===1) {//third party cookies are enabled
            }
        })
        </script>
        
        
        $.ajax({
        网址:'https://third-party-domain/third-party-cookies.php',
        数据类型:“jsonp”,
        }).done(功能已启用){
        如果(is_enabled==1){//第三方cookie已启用
        }
        })
        
        下面是第三方cookies.php代码。这必须托管在不同的域上。服务器必须支持PHP:

        <?php
        
        header('Cache-Control: no-store');
        header('Content-Type: text/javascript');
        
        if ($_GET['callback']=='') {
            echo 'alert("Error: A callback function must be specified.")';
        }
        elseif (!isset($_GET['cookieName'])) {// Cookie not set yet
            $cookieName = strtr((string)$_SERVER['UNIQUE_ID'], '@', '_');
            while (isset($_COOKIE[$cookieName]) || $cookieName=='') {
                $cookieName = dechex(mt_rand());// Get random cookie name
            }
            setcookie($cookieName, '3rd-party', 0, '/');
            header('Location: '.$_SERVER['REQUEST_URI'].'&cookieName='.$cookieName);
        }
        elseif ($_COOKIE[$_GET['cookieName']]=='3rd-party') {// Third party cookies are enabled.
            setcookie($_GET['cookieName'], '', -1, '/'); // delete cookie
            echo $_GET['callback'].'(1)';
        }
        else {// Third party cookies are not enabled.
            echo $_GET['callback'].'(0)';
        }
        

        我确实试过了,但没用。实际上,我们正在白标签域上运行一个白标签应用程序,
        
        <script>
        function myCallback(is_enabled) {
            if (is_enabled===1) {//third party cookies are enabled
            }
        }
        </script>
        <script src="https://third-party-domain/third-party-cookies.php?callback=myCallback"></script>
        
        <script>
        $.ajax({
            url: 'https://third-party-domain/third-party-cookies.php',
            dataType: 'jsonp',
        }).done(function(is_enabled) {
            if (is_enabled===1) {//third party cookies are enabled
            }
        })
        </script>
        
        <?php
        
        header('Cache-Control: no-store');
        header('Content-Type: text/javascript');
        
        if ($_GET['callback']=='') {
            echo 'alert("Error: A callback function must be specified.")';
        }
        elseif (!isset($_GET['cookieName'])) {// Cookie not set yet
            $cookieName = strtr((string)$_SERVER['UNIQUE_ID'], '@', '_');
            while (isset($_COOKIE[$cookieName]) || $cookieName=='') {
                $cookieName = dechex(mt_rand());// Get random cookie name
            }
            setcookie($cookieName, '3rd-party', 0, '/');
            header('Location: '.$_SERVER['REQUEST_URI'].'&cookieName='.$cookieName);
        }
        elseif ($_COOKIE[$_GET['cookieName']]=='3rd-party') {// Third party cookies are enabled.
            setcookie($_GET['cookieName'], '', -1, '/'); // delete cookie
            echo $_GET['callback'].'(1)';
        }
        else {// Third party cookies are not enabled.
            echo $_GET['callback'].'(0)';
        }