检查是否启用了第三方cookie

Mau*_*oer 48 javascript cookies

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

Ala*_* H. 70

技术背景

第三方通过HTTP设置和读取cookie(不是在JavaScript中).

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

  1. 第三方设置cookie的地方
  2. 第二种,具有不同的响应,取决于浏览器是否在第二次请求中将cookie发送回同一第三方.

由于DOM安全模型,我们无法使用XMLHTTPRequest(Ajax).

显然,您无法并行加载这两个脚本,或者第二个请求可能第一个请求的响应返回之前进行,并且测试cookie将不会被设置.

代码示例

鉴于:

  1. .html文件位于一个域上,并且

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

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>
Run Code Online (Sandbox Code Playgroud)

第一个第三方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();
Run Code Online (Sandbox Code Playgroud)

第二个第三方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'); ?>);
Run Code Online (Sandbox Code Playgroud)

最后一行使用三元运算符输出文字Javascript truefalse取决于测试cookie是否存在.

在这里测试一下.

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

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

  • 我从上面删除了一些过时的评论,但我在@MaheshKulkarni 的有用说明的几天内修复了我的示例测试。由于我以前的网络主机在处理我的 SSL 续订时遇到了史诗般的失败,我会遇到问题。如果将来测试中断,请告诉我:https://alanhogan.com/contact?reason=3rd%20party%20cookie%20test (2认同)
  • @AlanH,你知道这个解决方案目前是否仍在 Chrome(一般基于 Chromium 的浏览器)中工作吗?它适用于 Firefox,但不适用于 Chrome 或 Brave。即使在设置中允许所有 cookie,第三方 cookie 也始终显示为禁用。如果有这方面知识的人能够插话,我将不胜感激。 (2认同)

Goj*_*zic 42

这是一个纯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" />
Run Code Online (Sandbox Code Playgroud)

客户端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);
Run Code Online (Sandbox Code Playgroud)

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

  • 如果`start.html`文件应该消失,文件的内容是:`<body> <script> if(window.parent){if(/thirdparty=yes/.test(document.cookie)) {window .parent.postMessage('MM:3PCsupported','*'); } else {window.parent.postMessage('MM:3PCunsupported','*'); } </ script> </ body>` (3认同)
  • 到目前为止,这是最好的答案 (3认同)
  • 最新的 Chrome 更新似乎已被破坏,其中同站点限制非常严格 (3认同)

Gre*_*cki 7

Alan的解决方案很棒,但您不必使用PHP或任何其他服务器端编程语言.

至少如果你使用nginx.:)

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

Nginx配置启动

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;
Run Code Online (Sandbox Code Playgroud)

第一个第三方"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();';
    }
Run Code Online (Sandbox Code Playgroud)

第二个第三方"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);';
    }
Run Code Online (Sandbox Code Playgroud)

Nginx配置结束

}
Run Code Online (Sandbox Code Playgroud)


附注:

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


Mar*_*c B 1

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

如果您有一些特定的用途,例如检查广告是否被阻止(这也会阻止第 3 方跟踪 cookie),您可以检查广告服务器的内容是否在页面的 DOM 内,但您无法查看广告服务器的内容是否在页面的 DOM 内。饼干就在那里。