web-dev-qa-db-fra.com

Vérifiez si les cookies tiers sont activés

J'ai une application qui doit vérifier si le navigateur client a activé les cookies tiers. Est-ce que quelqu'un sait comment faire cela en JavaScript?

48
Maurits de Boer

Contexte technique

Le tiers définit et lit les cookies sur HTTP (pas en JavaScript).

Nous avons donc besoin de deux demandes à un domaine externe pour tester si les cookies tiers sont activés:

  1. Un où le tiers place le cookie (s)
  2. Le second, avec une réponse différente selon que le navigateur a renvoyé le ou les cookies au même tiers dans une deuxième demande.

Nous ne pouvons pas utiliser XMLHTTPRequest (Ajax) en raison du modèle de sécurité DOM.

De toute évidence, vous ne pouvez pas charger les deux scripts en parallèle, ou la deuxième demande peut être effectuée avant la réponse de la première demande revient, et le ou les cookies de test n'auront pas été définis.

Exemple de code

Donné:

  1. Le .html le fichier est sur un domaine, et

  2. Le .js.php les fichiers sont sur un second domaine, nous avons:

La page de test HTML

Enregistré sous 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>

Le premier fichier JavaScript tiers

Enregistré sous step1.js.php

Ceci est écrit en PHP afin que nous puissions définir des cookies lors du chargement du fichier. (Cela pourrait bien sûr être écrit dans n'importe quelle langue, ou même être fait dans des fichiers de configuration de serveur).)

<?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();

Le deuxième fichier JavaScript tiers

Enregistré sous step2.js.php

Ceci est écrit en PHP afin que nous puissions lire les cookies, côté serveur, avant de répondre. Nous effaçons également le cookie afin que le test puisse être répété (si vous voulez jouer avec les paramètres du navigateur et retenter).

<?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'); ?>);

La dernière ligne utilise l'opérateur ternaire pour sortir un littéral Javascript true ou false selon que le cookie de test était présent.

Testez-le ici .

Disponible pour votre plaisir de test sur https://alanhogan.github.io/web-experiments/3rd/third-party-cookies.html .

(Enfin, ( n'utilisez pas le serveur de quelqu'un d'autre pour tester les cookies tiers sans leur autorisation. Cela pourrait se casser spontanément ou injecter des logiciels malveillants. Et c'est dur.)

68
Alan H.

Voici une solution JS pure ne nécessitant aucun code côté serveur, elle peut donc fonctionner à partir d'un CDN statique: https://github.com/mindmup/3rdpartycookiecheck - le premier script définit le cookie dans le code , puis redirige vers un deuxième script qui publiera un message dans la fenêtre parent.

Vous pouvez essayer une version live en utilisant https://jsfiddle.net/tugawg8y/

hTML côté client:

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

jS côté client:

 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);

Bien sûr, cela nécessite que le client exécute JavaScript, ce qui est un inconvénient par rapport aux solutions basées sur serveur; d'un autre côté, c'est plus simple, et vous posiez des questions sur une solution JS.

42
Gojko Adzic

la solution d'Alan est génial, mais vous n'avez pas besoin d'utiliser PHP ou tout autre langage de programmation côté serveur.

Au moins si vous utilisez nginx . :)

Il s'agit d'une configuration côté serveur * nginx pure pour la solution d'Alan:

Démarrage de la configuration 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;

Le premier "fichier JavaScript" tiers - servi par 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();';
    }

Le deuxième "fichier JavaScript" tiers - servi par 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);';
    }

Fin de configuration Nginx

}


Notes annexes:

  • Ouais, ouais, je sais que IfIsEvil ,
  • J'ai gardé les noms se terminant par ".php" pour une compatibilité complète avec "La page de test HTML" d'Alan (third-party-cookies.html),
  • Vous pouvez également déplacer la ligne commune "définition de l'en-tête Content-Type" des deux emplacements vers la section server (étendue) de la configuration - je l'ai gardée de cette façon pour la traduction "1: 1". .
7
Greg Dubicki

En théorie, vous auriez juste une page appelant quelque part qui définirait un cookie tiers, puis vérifierait l'existence de ce cookie. Cependant, la sécurité standard du navigateur ne permet pas aux scripts du domaine A de faire quoi que ce soit avec les cookies définis sur les domaines B, C, etc. vous ne pouvez pas accéder aux cookies "étrangers".

Si vous avez un usage spécifique à l'esprit, comme vérifier si les annonces sont bloquées (ce qui bloquerait également le cookie de suivi tiers), vous pouvez vérifier si le contenu du serveur de publicité se trouve dans le DOM de la page, mais vous ne pouvez pas voir si le le cookie est là.

1
Marc B

Détection de cookies tiers avec liste blanche des URL

Alan H & Gojko Adzic sont assez bons pour la majorité des cas d'utilisation, mais ces solutions ne fonctionneront pas si vous voulez que vos utilisateurs ne liste blanche des cookies tiers que pour certains domaines.

Je présente une version légèrement modifiée de Gojko Adzic 's answer

Pour cela, nous avons besoin de deux domaines:

  • Domaine 1, c'est la page que votre utilisateur accède, il définit initialement tpc=pending, puis il redirige vers le domaine 2
  • Le domaine 2 injecte l'url du domaine 1 dans un iFrame, tente de définir un cookie tpc=true et redirige vers le domaine 1
  • Maintenant, le domaine 1 lit le cookie tpc et vérifie si son true, si nous obtenons la valeur true, les cookies tiers sont autorisés s'il est toujours dans pending cookies tiers sont bloqués bloqués.

Maintenant, vous pouvez demander à vos utilisateurs de mettre sur liste blanche (autoriser les cookies tiers) [~ # ~] uniquement [~ # ~] pour Domain 1, également par cette technique, la détection par un tiers sera accurate si les utilisateurs ont mis votre domaine en liste blanche.


Ceci est testé dans Chrome 74, 75, 76 & Edge 78

Malheureusement, Mozilla ne fournit pas de liste blanche d'URL comme Chrome le fait et Safari possède ses propres mécanismes de détection des cookies tiers (ITP).

P.S. Va télécharger cette démo dans mon github quand j'aurai le temps.

0
yashhy