技术背景
第三方通过 HTTP(不是 JavaScript)设置和读取 cookie。
因此,我们需要向外部域发送两个请求来测试是否启用了第三方 cookie:
- 第三方设置 cookie 的一种方式
- 第二种,根据浏览器是否在第二个请求中将 cookie 发送回同一第三方,会产生不同的响应。
由于 DOM 安全模型,我们无法使用 XMLHTTPRequest (Ajax)。
显然你不能并行加载两个脚本,否则可能会发出第二个请求before第一个请求的响应返回,并且测试 cookie 将不会被设置。
代码示例
Given:
The .html
文件位于一个域中,并且
The .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…';
// 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 编写的,因此我们可以在文件加载时设置 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 文字true
or false
取决于测试 cookie 是否存在。
在这里测试一下.
您可以在以下位置享受测试乐趣https://alanhogan.github.io/web-experiments/3rd/third-party-cookies.html.
(最后一点——不要使用别人的服务器未经许可测试第三方 cookie。它可能会自发崩溃或注入恶意软件。而且这很粗鲁。)