web-dev-qa-db-fra.com

Définition de cookies interdomaines dans Safari

Le bookmarklet de Evernote est capable de le faire. Par conséquent, la réponse la plus votée ne répond pas, même si la prime lui sera versée (de manière non productive).

Je dois appeler le domaine A.com (qui définit les cookies avec http) du domaine B.com . Tout ce que je fais sur le domaine B.com est (javascript): 

var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = "A.com/setCookie?cache=1231213123";
head.appendChild(script);

Cela configure le cookie sur A.com sur chaque navigateur que j'ai testé, à l'exception de Safari . Étonnamment, cela fonctionne dans IE6, même sans les en-têtes P3P.

Y at-il un moyen de faire ce travail dans Safari?

55
Luca Matteis

À partir du Safari Developer FAQ :

Safari est livré avec une politique de cookie conservatrice qui limite les écritures de cookie aux seules pages choisies ("visitées") par l'utilisateur. Cette stratégie conservatrice par défaut peut confondre les sites basés sur des cadres qui tentent d'écrire des cookies et échouent.

Je n'ai trouvé aucun moyen de contourner cela.

Si cela vaut la peine, Chrome ne configure pas les cookies non plus si vous utilisez la méthode <script> qui ajoute, mais si vous avez un <img> caché avec la même source, Chrome fonctionne en plus du reste des navigateurs Safari)

52
Paolo Bergantino
13
Alec Smart

Méthode de travail 2014-2016:

Vous devez faire window.open au domaine/assigner un cookie/fermer le popup, le domaine est maintenant sauvegardé. 

Article original @ PHP plusieurs cookies ne fonctionnent pas dans les navigateurs iPad/iPhone

6
MKN Web Solutions

Il existe un truc diabolique dans l’hypothèse où Flash est installé.

Je ne sais pas si cela fonctionne toujours ou non, mais Flash'es "Objets partagés locaux", alias Cookies Flash, pourrait vous aider à faire le tour des politiques de Safari en matière de domaine identique. 

Didacticiel local d'objets partagés

Cependant, il peut être compliqué à mettre en œuvre, pour le moins. 

De plus, les LSO deviennent un cauchemar pour la sécurité: 

Alors réfléchissez bien avant de les utiliser. 

4
Kent Fredric

Il y a une solution de contournement appropriée pour ce travail en 2015. Disons qu'il existe un site Web y.com qui inclut iframe avec le site x.com. Le x.com iframe veut stocker un cookie. Cela n’est pas autorisé par la politique de Safari, cependant, y.com est capable de le stocker. Donc, y.com doit écouter les messages de x.com, puis stocker le cookie lui-même.

var _cookieEvMth = window.addEventListener ? "addEventListener" : "attachEvent";
var _cookieEvAction = window[_cookieEvMth];
var _cookieEv = _cookieEvMth == "attachEvent" ? "onmessage" : "message";
_cookieEvAction(_cookieEv, function(evt){
  if(evt.data.indexOf('cookieset')!=-1){
    var datack = evt.data.split('|');
    YOUR_CUSTOM_COOKIE_SAVE_METHOD(datack[1],datack[2],datack[3]);
  }
},false);

Lorsque x.com doit stocker le cookie, il doit envoyer un message à y.com:

window.parent.postMessage('cookieset|'+ckName+'|'+ckVal+'|'+days,'*');

Vous pouvez également travailler de manière à poster un message sur l'iframe si vous souhaitez lire le cookie. Ou vous pouvez l'inclure en tant que paramètre dans l'URL x.com iframe à l'aide de javascript:

iframe.setAttribute('url','x.com/?cookieval='+YOUR_COOKIE_GET_METHOD('cookiename'));
3
user1718507

Une publication dans un <iframe> masqué peut vous permettre de contourner cette restriction dans Safari - http://Gist.github.com/586182 :

<?php
  header('P3P: CP=HONK');
  setcookie('test_cookie', '1', 0, '/');
?>
<div id="test_cookie" style="position: absolute; top: -10000px"></div>
<script>
  window.setTimeout(function() {
    if (document.cookie.indexOf('test_cookie=1') < 0) {
      var      
        name = 'test_cookie',
        div = document.getElementById(name),
        iframe = document.createElement('iframe'),
        form = document.createElement('form');

      iframe.name = name;
      iframe.src = 'javascript:false';
      div.appendChild(iframe);

      form.action = location.toString();
      form.method = 'POST';
      form.target = name;
      div.appendChild(form);

      form.submit();
    }
  }, 10);
</script>
3
daaku

Une solution de contournement que nous venons juste de trouver dans mon travail consistait à définir le cookie via une fenêtre.open () - ce n'est peut-être pas optimal pour vous (vous aurez une fenêtre assoiffée de fesses ouverte), mais cela a bien fonctionné pour nous. . Nous devions quand même ouvrir une fenêtre popup pour l'authentification OAuth.

Donc, le but de ce que nous avons fait était:

  1. L'utilisateur clique sur un lien de B.com
  2. La fenêtre contextuelle s'ouvre sur A.com/setCookie
  3. A.com définit son cookie, puis redirige vers B.com au bon endroit

Encore une fois, pas valable dans toutes les solutions, mais cela a fonctionné dans la nôtre. J'espère que cela t'aides.

2
umbrae

Je sais que cette question est assez ancienne, mais cela m'a aidé à résoudre le problème des cookies:

var cookieForm = document.createElement("form");
cookieForm.action = "A.com/setCookie?cache=1231213123";
cookieForm.method = "post";
document.body.appendChild(cookieForm);

cookieForm.submit();

L'idée de publier un formulaire sur une page qui définit vos cookies.

2
ADOConnection

*EDIT * Cette solution de contournement a été signalée fermée dans WebKit.

Luca

Ok, donc cette réponse a deux ans, mais ... vous pouvez définir un cookie depuis une iframe si vous postez un formulaire dans une iframe masquée. Vous pouvez le faire en créant un formulaire:

<form id="myiframe" action="http://yourdomain.com" method="POST" target="iframe_target">

Ensuite, en Javascript, obtenez une référence au formulaire et appelez submit:

document.getElementsByTagName('form')[0].submit();

Vous pouvez écouter le chargement de l'iframe ou demander à votre page d'action iframe de générer du code javascript indiquant la charge. J'ai testé cela dans Safari et Chrome, et cela fonctionne.

À votre santé.

1
thesmart

J'ai effectué des recherches approfondies à ce sujet lorsque j'essayais de déployer un site utilisant Windows Live ID, ce qui dépendait de la possibilité de définir des cookies tiers afin de vous déconnecter. Cela n'a tout simplement pas fonctionné. Nous ne pourrions rien faire pour que cela fonctionne. L’équipe Live ID a également mené une enquête approfondie et leur réponse était "ne peut pas le faire fonctionner".

0
Brad Wilson

Notez cette ligne:

script.src = "A.com/setCookie?cache=1231213123";

Je ne pouvais pas le faire fonctionner avant d’ajouter le http, c.-à-d.

script.src = "http://A.com/setCookie?cache=1231213123";
0
Mossy

Cela ne fonctionnera peut-être pas pour tout le monde, mais je suis tombé sur ce problème parce que je servais une application React à partir d'un hôte différent de celui de l'API et que la solution qui a finalement fonctionné consistait à utiliser DNS:

Notre client était desservi par www.company-name.com et notre API par company-name.herokuapp.com. En effectuant unCNAMErecord api.company-name - company-name.herokuapp.com, et obligeant notre client à utiliser ce sous-domaine pour les appels d'API, Safari a cessé de la considérer comme un "tiers". biscuit.

L'avantage, c'est que très peu de code est impliqué et qu'il utilise des éléments bien établis ... L'inconvénient est que vous avez besoin d'un contrôle/d'un droit de propriété sur l'hôte de l'API si vous souhaitez utiliser https - ils ont besoin d'un certificat valide. pour le domaine client, ou les utilisateurs recevront un avertissement de certificat - cela ne fonctionnera donc pas (du moins pas pour les utilisateurs finaux) si l'API en question n'est ni la vôtre ni celle d'un partenaire.

0
DrShaffopolis

Placez ce code JavaScript sur la page des requêtes inter-domaines, http://example1.com/index.html :

  <script>
  var gup = function(name, url) {
     if(!url) url = location.href;
     name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
     var regexS = "[\\?&]"+name+"=([^&#]*)";
     var regex = new RegExp( regexS );
     var results = regex.exec( url );
     return results == null ? null : results[1];
  }
  var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1 && navigator.userAgent && !navigator.userAgent.match('CriOS');
  var n = gup("activated");
  if(isSafari && n == null) {
     //browser is Safari and cookies have not yet been activated
     var current_url = location.protocol + '//' + location.Host + location.pathname;
     var query_string = '?callback=' + encodeURIComponent(current_url + '?activated=1');
     var new_url = 'http://example2.com/activate.php' + query_string;
     window.location.href = new_url;
  }
  //the rest of your code goes here, and you can now set cross-domain cookies on Safari
  </script>

Créez ensuite un fichier sur l'autre serveur, qui doit définir des cookies, http://example2.com/activate.php :

  <?php
  if(isset($_GET['callback'])) {
     header('Location: '.$_GET['callback']);
     exit();
  } else {
     //in case callback param is not set, simply go back to previous page
     echo "<script>";
     echo "window.history.back();";
     echo "</script>";
     exit();
  }
  ?>

Voici comment cela fonctionne: 

  1. Lors de la première visite de http://example1.com/index.html , il est vérifié si le navigateur est Safari et si un paramètre GET du nom "activé" n'existe pas. Si les deux conditions sont remplies (ce qui se produira lors de la première visite d'un navigateur Safari), le navigateur est alors redirigé vers http://example2.com/activate.php avec un paramètre GET, "callback", contenant l'URL appelante est accompagnée d'un paramètre "activé". 

  2. http://example2.com/activate.php redirige simplement vers l'URL contenue dans le paramètre GET, "callback". 

  3. Lorsque http: //example1.index.html est maintenant touché cette seconde fois après avoir été redirigé vers, le paramètre GET "activé" est maintenant défini, de sorte que la condition de l'étape 1 ne sera pas exécutée, permettant ainsi le script pour continuer l'exécution.

Cela répond à l'exigence de Safari selon laquelle le navigateur doit visiter le domaine tiers au moins une fois afin de pouvoir configurer les cookies.

0
Dane Iracleous

Il est intéressant de noter que cette restriction dans Safari ne s'applique pas à tous les sous-domaines. Donc, si vous visitez directement sitea.com, vous pouvez configurer les cookies de subdomain.sitea.com sans interaction directe de l'utilisateur (iframe/JavaScript).

Cela était pertinent pour mon cas lors du développement d'une API. Si vos visiteurs arrivent sur mysite.com et que vous souhaitez que du JavaScript interagisse avec votre API, si l'API est hébergée sur api.mysite.com, cela fonctionnera sous Safari.

0
Dom

Peut-être créer et cliquer de manière pragmatique et cliquer sur un lien avec un href="A.com/setCookie?cache=1231213123" et un attribut cible pointant vers un iframe caché. Cela peut contourner la politique de Safari en matière de navigation des utilisateurs pour l’installation de cookies (je n’ai pas Safari à tester.)

0
Zach

J'ai trouvé une solution simple. Vous avez juste besoin d’un cookie initial pour vérifier si la requête provient de la même origine ou non, sinon, vous devez restituer à iframe un script qui répètera cette requête, ayant déjà l’autorisation d’affecter un cookie. Ensuite, vous pouvez effectuer une autre demande directement via iframe en accédant à ce cookie. Cela m'a aidé dans mon système de suivi. Essayez, ça marche bien.

0
Placinta Alexandru