检查是否启用了第三方Cookie
我有一个应用程序需要检查客户端浏览器是否启用了第三方Cookie。 有谁知道如何在JavaScript中做到这一点?
技术背景
第三方通过HTTP设置&读取Cookie(而不是JavaScript)。
所以我们需要两个请求到外部域来testing是否启用了第三方cookie:
- 第三方设置cookie的地方
- 第二,根据浏览器是否在第二个请求中将cookie发送回相同的第三方,具有不同的响应。
由于DOM安全模型,我们不能使用XMLHTTPRequest(Ajax)。
很明显,你不能同时加载两个脚本,或者第二个请求可能在第一个请求的响应返回之前进行,并且testingcookie将不会被设置。
代码示例
鉴于:
-
.html
文件位于一个域中,而 -
.js.php
文件位于第二个域,我们有:
HTMLtesting页面
保存为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…'; // 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…</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编写的,所以我们可以将cookies设置为文件加载。 (当然,可以用任何语言编写,甚至可以在服务器configuration文件中完成)。
<?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编写的,所以我们可以在服务器端读取cookies,然后再回应。 我们也清除cookie,以便testing可以重复(如果你想浏览器设置,并重新尝试)。
<?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'); ?>);
最后一行使用三元运算符根据testingcookie是否存在输出一个true
Javascript true
或false
。
在这里testing 。
可以在https://alanhogan.github.io/web-experiments/3rd/third-party-cookies.html进行testing。;
(最后说明 – 不要使用他人的服务器在未经他们许可的情况下testing第三方cookie,这可能会自发破坏或者注入恶意软件,而且很粗鲁。)
这是一个纯JS解决scheme,不需要任何服务器端代码,所以它可以从一个静态的CDN工作: https : //github.com/mindmup/3rdpartycookiecheck – 第一个脚本在代码中设置cookie,然后redirect到第二个脚本这将会发布消息到父窗口。
你可以使用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,与基于服务器的解决scheme相比,这是一个不利的方面; 另一方面,它更简单,你在问一个JS解决scheme。
艾伦的解决scheme是伟大的,但你不必使用PHP或任何其他服务器端编程语言。
至less如果你使用nginx的话 。 🙂
这是Alan解决scheme的一个纯粹的* nginx服务器端configuration:
Nginx的configuration开始
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);'; }
Nginxconfiguration结束
}
边注:
- 是啊,是的,我知道如果我是魔鬼 ,
- 为了与Alan的“The HTML test page”(
third-party-cookies.html
)完全兼容,我保留了以“.php”结尾的名字, - 你也可以将两个位置的通用“设置Content-Type头”行移动到configuration的
server
部分(范围) – 我已经保持这种方式来保持它更“1:1”的翻译。
从理论上讲,你只是在某个地方设置一个页面调用来设置第三方cookie,然后检查cookie是否存在。 但是,标准的浏览器安全性不允许来自域A的脚本使用在域B,C等上设置的cookie进行任何操作。例如,您不能访问“外来”cookie。
如果你有一些具体的用法,例如检查广告是否被阻止(这也会阻止第三方跟踪cookie),你可以检查广告服务器的内容是否在页面的DOM内,但是你看不到cookies在那里。