检查是否启用了第三方cookie

时间:2010-08-23 18:59:11

标签: javascript cookies

我有一个应用程序需要检查客户端浏览器是否启用了第三方cookie。有谁知道如何在JavaScript中执行此操作?

6 个答案:

答案 0 :(得分:67)

技术背景

第三方设置&通过HTTP(而不是JavaScript)读取cookie。

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

  1. 第三方设置Cookie的地方
  2. 第二种,具有不同的响应,具体取决于浏览器是否在第二次请求中将cookie发送回同一第三方。
  3. 由于DOM安全模型,我们无法使用XMLHTTPRequest(Ajax)。

    显然你不能并行加载这两个脚本,或者第二个请求可以在之前第一个请求的响应使它返回,并且测试cookie将不会被设置。

    代码示例

    鉴于:

    1. .html文件位于一个域中,

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

    3. HTML测试页

      保存为third-party-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文件

      保存为step1.js.php

      这是用PHP编写的,因此我们可以在文件加载时设置cookie。 (当然,它可以用任何语言编写,甚至可以在服务器配置文件中完成。)

      <?php
        header('Content-Type: application/javascript; charset=UTF-8');
        // Set test cookie
        setcookie('third_party_c_t', 'hey there!', time() + 3600*24*2);
      ?>
      window._3rd_party_test_step1_loaded();
      

      第二个第三方JavaScript文件

      保存为step2.js.php

      这是用PHP编写的,所以我们可以在响应之前读取服务器端的cookie。我们还清除了cookie,以便可以重复测试(如果你想搞乱浏览器设置并重新尝试)。

      <?php
        header('Content-Type: application/javascript; charset=UTF-8');
        // Read test cookie, if there
        $cookie_received = (isset($_COOKIE['third_party_c_t']) && $_COOKIE['third_party_c_t'] == 'hey there!');
        // And clear it so the user can test it again 
        setcookie('third_party_c_t', '', time() - 3600*24);
      ?>
      window._3rd_party_test_step2_loaded(<?php echo ($cookie_received ? 'true' : 'false'); ?>);
      

      最后一行使用三元运算符输出文字Javascript truefalse,具体取决于测试Cookie是否存在。

      Test it here

      可在https://alanhogan.github.io/web-experiments/3rd/third-party-cookies.html获得您的测试乐趣。

      (最后一点 - 不要使用其他人的服务器在没有他们许可的情况下测试第三方cookie。它可能会自发破坏或注入恶意软件。而且这很粗鲁。)

答案 1 :(得分:41)

这是一个纯JS解决方案,不需要任何服务器端代码,所以它可以在静态CDN上工作:https://github.com/mindmup/3rdpartycookiecheck - 第一个脚本在代码中设置cookie,然后重定向到将发布的第二个脚本到父窗口的消息。

您可以使用https://jsfiddle.net/tugawg8y/

试用实时版本

客户端HTML:

third party cookies are <span id="result"/>
<iframe src="https://mindmup.github.io/3rdpartycookiecheck/start.html"
    style="display:none" />

客户端JS:

 var receiveMessage = function (evt) {
   if (evt.data === 'MM:3PCunsupported') {
     document.getElementById('result').innerHTML = 'not supported';
   } else if (evt.data === 'MM:3PCsupported') {
     document.getElementById('result').innerHTML = 'supported';
   }
 };
 window.addEventListener("message", receiveMessage, false);

当然,这需要客户端运行JavaScript,这与基于服务器的解决方案相比是一个缺点;另一方面,它更简单,你问的是JS解决方案。

答案 2 :(得分:6)

Alan's solution很棒,但您不必使用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;

第一个第三方“JavaScript文件” - 由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();';
    }

第二个第三方“JavaScript文件” - 由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配置结束

}


附注:

  • 是的,是的,我知道IfIsEvil
  • 我保留了以“.php”结尾的名字,以便与Alan的“HTML测试页面”(third-party-cookies.html)完全兼容,
  • 您还可以将两个位置的常见“设置内容类型标题”行移动到配置的server部分(范围) - 我保持这种方式以保持更多“1:1 “翻译。

答案 3 :(得分:1)

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

如果您有一些特定用途,例如检查广告是否被屏蔽(这也会阻止第三方跟踪Cookie),您可以检查广告服务器的内容是否在网页的DOM中,但您不能看看那里是否有cookie。

答案 4 :(得分:1)

我的解决方案的工作原理是从设置cookie的外部域加载