Cookies interdomaines

247

J'ai deux webapps WebApp1 et WebApp2 dans deux domaines différents.

  1. Je mets un cookie dans WebApp1 dans HttpResponse.
  2. Comment lire le même cookie de HttpRequest dans WebApp2?

Je sais que cela semble étrange car les cookies sont spécifiques à un domaine donné, et nous ne pouvons pas y accéder à partir de différents domaines; J'ai cependant entendu parler de cookies CROSS-DOMAIN qui peuvent être partagés entre plusieurs webapps. Comment mettre en œuvre cette exigence à l'aide de cookies CROSS-DOMAIN?

Remarque: j'essaye ceci avec des webapps J2EE

SundarJavaDeveloper
la source

Réponses:

130

Oui, il est absolument possible d'obtenir le cookie de domain1.com par domain2.com. J'ai eu le même problème pour un plugin social de mon réseau social, et après une journée de recherche j'ai trouvé la solution.

Tout d'abord, côté serveur, vous devez avoir les en-têtes suivants:

header("Access-Control-Allow-Origin: http://origin.domain:port");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Methods: GET, POST");
header("Access-Control-Allow-Headers: Content-Type, *");

Dans le fichier PHP, vous pouvez utiliser $_COOKIE[name]

Deuxièmement, côté client:

Dans votre demande ajax, vous devez inclure 2 paramètres

crossDomain: true
xhrFields: { withCredentials: true }

Exemple:

type: "get",
url: link,
crossDomain: true,
dataType: 'json',
xhrFields: {
  withCredentials: true
}
Ludovic
la source
6
Ou si vous ne voulez pas filtrer sur l'origine, utilisez simplement $ _SERVER ['HTTP_ORIGIN'] au lieu de *
Joel Teply
1
Ce sont les seules choses qui ont fonctionné pour moi. De plus, * n'a pas été accepté comme origine, donc le conseil de @Joel Teply est nécessaire.
Deviné le
4
Cela ne fonctionnera pas si les cookies tiers sont désactivés (automatique pour certaines situations de navigateur). Voir blog.zok.pw/web/2015/10/21/3rd-party-cookies-in-practice et allannienhuis.com/archives/2013/11/03/… pour plus d'informations.
robocat
4
N'utilisez pas l'astuce de Joel, car elle est "essentiellement" la même chose que de la définir sur "*", ce qui peut ouvrir des trous de sécurité subtils et est donc déconseillé, voir stackoverflow.com/questions/12001269/…
rogerdpack
5
côté serveur de quel domaine?
Nick Manning
127

Comme d'autres le disent, vous ne pouvez pas partager de cookies, mais vous pouvez faire quelque chose comme ceci:

  1. centraliser tous les cookies dans un seul domaine, disons cookiemaker.com
  2. lorsque l'utilisateur fait une demande à example.com, vous le redirigez vers cookiemaker.com
  3. cookiemaker.com le redirige vers example.com avec les informations dont vous avez besoin

Bien sûr, ce n'est pas complètement sécurisé, et vous devez créer une sorte de protocole interne entre vos applications pour ce faire.

Enfin, ce serait très ennuyeux pour l'utilisateur si vous faites quelque chose comme ça dans chaque demande, mais pas si ce n'est que la première.

Mais je pense qu'il n'y a pas d'autre moyen ...

alcuadrado
la source
44
S'il n'y a pas d'autre moyen, comment fonctionne StackExchange / OpenID?
Hawken
60
@Hawken StackExchange / OpenID suit le même processus que celui décrit ci-dessus. Vous êtes dirigé vers un autre site (SO> SX), confirmez votre identité, puis vous êtes redirigé vers SO avec les informations dont vous avez besoin. La spécification OpenID explique plus, bien que Wikipedia le fasse plus clairement .
Nick Q.
1
Tous les utilisateurs sont actuellement connectés sur cookiemaker.com. Et il redirige l'utilisateur vers les différents sites avec un message spécial et sécurisé qui vérifie qu'ils sont connectés et qui ils sont. Comment le mettre en œuvre dépend de vous, il existe une infinité de façons de le faire. Vous pouvez peut-être utiliser ceci: jwt.io
alcuadrado
8
@ Andrew_1510 cookiebakerserait mieux ;-)
Richard Turner
1
Voici le post avec tag d'image, est-ce une meilleure solution ?
shaijut
70

Pour autant que je sache, les cookies sont limités par la politique de la "même origine". Cependant, avec CORS, vous pouvez recevoir et utiliser les cookies "Serveur B" pour établir une session persistante de "Serveur A" sur "Serveur B".

Bien que cela nécessite des en-têtes sur le "serveur B":

Access-Control-Allow-Origin: http://server-a.domain.com
Access-Control-Allow-Credentials: true

Et vous devrez envoyer le drapeau " withCredentials " sur toutes les requêtes "Server A" (ex:xhr.withCredentials = true; )

Vous pouvez lire à ce sujet ici:

http://www.html5rocks.com/en/tutorials/cors/

https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS

Vitae Aliquam
la source
11
Cela ne fonctionnera pas pour certains utilisateurs car les cookies CORS ne fonctionneront pas si les cookies tiers sont désactivés, par exemple Safari par défaut, par exemple les paramètres de Mozilla . Google plus d'exemples et un article expliquant pourquoi Facebook n'utilise pas de cookies tiers.
robocat
1
L'échange de pile / openID utilise-t-il CORS?
RayLoveless
1
FWIW Je viens de tester un CORS normal avec des références XHR et cela a fonctionné sur FF / Safari / Chrome ... bien que je ne doute pas que Facebook / Google utilisent des schémas plus sophistiqués
rogerdpack
30

Les cookies interdomaines n'existent pas. Vous pouvez partager un cookie entre foo.example.comet bar.example.commais jamais entre example.comet example2.comet c'est pour des raisons de sécurité.

Darin Dimitrov
la source
1
Salut merci pour la réponse, pouvez-vous ajouter plus de clarté sur la partie configuration, comment créer / configurer un domaine et un sous-domaine dans un environnement j2ee ???
SundarJavaDeveloper
1
Il s'agit d'une question plus adaptée à serverfault.com où vous obtiendrez des réponses d'experts du domaine.
Darin Dimitrov
Salut, j'ai essayé d'avoir deux webapps WebApp.domain.com ==> ici j'ajoute un cookie en réponse comme suit: Cookie cookie = nouveau cookie ("namedCookie", "test"); cookie.setDomain (". domain.com"); response.addCookie (cookie); WebApp1.domain.com ==> Ici, j'ai essayé d'accéder au cookie comme suit, mais je ne peux pas accéder à Cookie [] cks = request.getCookies (); for (int i = 0; i <cks.length; i ++) {out.print ("cookie trouvé" + cks [i] .getValue ()); } Une idée à ce sujet?
SundarJavaDeveloper
2
souvent répété mais pas vrai, voir ma réponse ci-dessous ou ici stackoverflow.com/questions/16186645/…
Raphael Jeger
4
Comment partager des cookies entre foo.example.comet bar.example.com?
Jeff Tian
24

La solution la plus intelligente est de suivre le chemin de Facebook à ce sujet. Comment Facebook sait-il qui vous êtes lorsque vous visitez un domaine? C'est en fait très simple :

Le bouton J'aime permet en fait à Facebook de suivre tous les visiteurs du site externe, qu'ils cliquent ou non dessus. Facebook peut le faire car il utilise un iframe pour afficher le bouton. Un iframe est quelque chose comme une fenêtre de navigateur intégrée dans une page. La différence entre l'utilisation d'un iframe et d'une simple image pour le bouton est que l' iframe contient une page Web complète - de Facebook . Il n'y a pas grand-chose sur cette page, à l'exception du bouton et des informations sur le nombre de personnes qui ont aimé la page actuelle.

Ainsi, lorsque vous voyez un bouton J'aime sur cnn.com, vous visitez en fait une page Facebook en même temps. Cela permet à Facebook de lire un cookie sur votre ordinateur, qu'il a créé la dernière fois que vous vous êtes connecté à Facebook.

Une règle de sécurité fondamentale dans chaque navigateur est que seul le site Web qui a créé un cookie peut le lire ultérieurement. Et c'est l'avantage de l'iframe: il permet à Facebook de lire votre cookie Facebook même lorsque vous visitez un autre site Web. C'est ainsi qu'ils vous reconnaissent sur cnn.com et y présentent vos amis.

La source:

Morteza Shahriari Nia
la source
6
Je pense qu'un iframe se classerait rarement comme la meilleure ou la façon la plus intelligente de faire quoi que ce soit .. mais c'est la plus simple.
Orun
13

Faites ce que fait Google. Créez un fichier PHP qui définit le cookie sur les 3 domaines. Ensuite, sur le domaine où le thème va être défini, créez un fichier HTML qui chargerait le fichier PHP qui définit le cookie sur les 2 autres domaines. Exemple:

<html>
   <head></head>
   <body>
      <p>Please wait.....</p>
      <img src="http://domain2.com/setcookie.php?theme=whateveryourthemehere" />
      <img src="http://domain3.com/setcookie.php?theme=whateveryourthemehere" />
   </body>
</html>

Ajoutez ensuite un rappel onload sur la balise body. Le document ne se chargera que lorsque les images se chargeront complètement, c'est-à-dire lorsque les cookies sont définis sur les 2 autres domaines. Rappel en charge:

<head>
   <script>
   function loadComplete(){
      window.location="http://domain1.com";//URL of domain1
   }
   </script>
</head>
<body onload="loadComplete()">

setcookie.php

Nous installons les cookies sur les autres domaines en utilisant un fichier PHP comme celui-ci:

<?php
if(isset($_GET['theme'])){
   setcookie("theme", $_GET['theme'], time()+3600);
}
?>

Désormais, les cookies sont définis sur les trois domaines.

Hossain Khademian
la source
2
Cela ne fonctionne pas si la fonction «Bloquer les cookies tiers» est activée.
Jens
11

Vous ne pouvez pas partager de cookies entre plusieurs domaines. Vous pouvez cependant autoriser l'accès à tous les sous-domaines. Pour autoriser tous les sous-domaines example.comà avoir accès, définissez le domaine sur .example.com.

Il n'est cependant pas possible de donner otherexample.comaccès aux example.comcookies de.

Daniel Egeberg
la source
27
comment se fait-il que les .google.comcookies apparaissent lors de la navigation sur YouTube?
Hawken
20
Balises Google Analytics. Ces cookies proviennent de google.com, pas de youtube.com.
Entendu
8

Vous pouvez tenter de pousser la valeur du cookie vers un autre domaine à l'aide d'une balise d'image.

Votre kilométrage peut varier lorsque vous essayez de le faire, car certains navigateurs nécessitent que vous ayez une politique P3P appropriée sur le domaine WebApp2 ou le navigateur rejettera le cookie.

Si vous regardez la politique de plus.google.com p3p, vous verrez que leur politique est:

CP = "Ce n'est pas une politique P3P! Voir http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 pour plus d'informations."

c'est la politique qu'ils utilisent pour leurs boutons +1 pour ces demandes interdomaines.

Un autre avertissement est que si vous êtes sur https, assurez-vous que la balise d'image pointe également vers une adresse https sinon les cookies ne seront pas définis.

Bryan Focht
la source
2
Envie d'élaborer un peu?
fréquent
5

Il y a un bon aperçu de la façon dont Facebook le fait ici sur nfriedly.com

Il existe également une empreinte digitale du navigateur, qui n'est pas la même chose qu'un cookie, mais sert un objectif similaire en ce qu'il vous aide à identifier un utilisateur avec un certain degré de certitude. Il y a un article ici sur Stack Overflow qui fait référence à une méthode d'empreinte digitale

byZero
la source
1

On peut utiliser des iframes invisibles pour obtenir les cookies. Disons qu'il y a deux domaines, a.com et b.com. Pour l'index.html du domaine a.com on peut ajouter (remarquez hauteur = 0 largeur = 0):

<iframe height="0" id="iframe" src="http://b.com" width="0"></iframe>

De cette façon, votre site Web recevra des cookies b.com en supposant que http://b.com définit les cookies.

La prochaine chose serait de manipuler le site à l'intérieur de l'iframe via JavaScript. Les opérations à l'intérieur d'iframe peuvent devenir un défi si l'on ne possède pas le deuxième domaine. Mais en cas d'accès aux deux domaines, renvoyer la bonne page Web au src d'iframe devrait donner les cookies que l'on souhaite obtenir.

Vadym Tyemirov
la source
5
Juste un avertissement: il y a de sérieux problèmes avec les cookies dans les iframes sur Safari. Ils ne fonctionnent apparemment pas dans plusieurs domaines.
mvds
1
function GetOrder(status, filter) {
    var isValid = true; //isValidGuid(customerId);
    if (isValid) {
        var refundhtmlstr = '';
        //varsURL = ApiPath + '/api/Orders/Customer/' + customerId + '?status=' + status + '&filter=' + filter;
        varsURL = ApiPath + '/api/Orders/Customer?status=' + status + '&filter=' + filter;
        $.ajax({
            type: "GET",
            //url: ApiPath + '/api/Orders/Customer/' + customerId + '?status=' + status + '&filter=' + filter,
            url: ApiPath + '/api/Orders/Customer?status=' + status + '&filter=' + filter,
            dataType: "json",
            crossDomain: true,
            xhrFields: {
                withCredentials: true
            },
            success: function (data) {
                var htmlStr = '';
                if (data == null || data.Count === 0) {
                    htmlStr = '<div class="card"><div class="card-header">Bu kriterlere uygun sipariş bulunamadı.</div></div>';
                }
                else {
                    $('#ReturnPolicyBtnUrl').attr('href', data.ReturnPolicyBtnUrl);
                    var groupedData = data.OrderDto.sort(function (x, y) {
                        return new Date(y.OrderDate) - new Date(x.OrderDate);
                    });
                    groupedData = _.groupBy(data.OrderDto, function (d) { return toMonthStr(d.OrderDate) });
                    localStorage['orderData'] = JSON.stringify(data.OrderDto);

                    $.each(groupedData, function (key, val) {

                        var sortedData = groupedData[key].sort(function (x, y) {
                            return new Date(y.OrderDate) - new Date(x.OrderDate);
                        });
                        htmlStr += '<div class="card-header">' + key + '</div>';
                        $.each(sortedData, function (keyitem, valitem) {
                            //Date Convertions
                            if (valitem.StatusDesc != null) {
                                valitem.StatusDesc = valitem.StatusDesc;
                            }

                            var date = valitem.OrderDate;
                            date = date.substring(0, 10).split('-');
                            date = date[2] + '.' + date[1] + '.' + date[0];
                            htmlStr += '<div class="col-lg-12 col-md-12 col-xs-12 col-sm-12 card-item clearfix ">' +
                        //'<div class="card-item-head"><span class="order-head">Sipariş No: <a href="ViewOrderDetails.html?CustomerId=' + customerId + '&OrderNo=' + valitem.OrderNumber + '" >' + valitem.OrderNumber + '</a></span><span class="order-date">' + date + '</span></div>' +
                        '<div class="card-item-head"><span class="order-head">Sipariş No: <a href="ViewOrderDetails.html?OrderNo=' + valitem.OrderNumber + '" >' + valitem.OrderNumber + '</a></span><span class="order-date">' + date + '</span></div>' +
                        '<div class="card-item-head-desc">' + valitem.StatusDesc + '</div>' +
                        '<div class="card-item-body">' +
                            '<div class="slider responsive">';
                            var i = 0;
                            $.each(valitem.ItemList, function (keylineitem, vallineitem) {
                                var imageUrl = vallineitem.ProductImageUrl.replace('{size}', 200);
                                htmlStr += '<div><img src="' + imageUrl + '" alt="' + vallineitem.ProductName + '"><span class="img-desc">' + ProductNameStr(vallineitem.ProductName) + '</span></div>';
                                i++;
                            });
                            htmlStr += '</div>' +
                        '</div>' +
                    '</div>';
                        });
                    });

                    $.each(data.OrderDto, function (key, value) {
                        if (value.IsSAPMigrationflag === true) {
                            refundhtmlstr = '<div class="notify-reason"><span class="note"><B>Notification : </B> Geçmiş siparişleriniz yükleniyor.  Lütfen kısa bir süre sonra tekrar kontrol ediniz. Teşekkürler. </span></div>';
                        }
                    });
                }
                $('#orders').html(htmlStr);
                $("#notification").html(refundhtmlstr);
                ApplySlide();
            },
            error: function () {
                console.log("System Failure");
            }
        });
    }
}

Web.config

Inclure l'origine de l'interface utilisateur et définir Autoriser les informations d'identification sur true

<httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="http://burada.com" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
        <add name="Access-Control-Allow-Credentials" value="true" />
      </customHeaders>
    </httpProtocol>
user7712621
la source
1

J'ai créé un module NPM, qui vous permet de partager des données stockées localement sur plusieurs domaines: https://www.npmjs.com/package/cookie-toss

En utilisant un iframe hébergé sur le domaine A, vous pouvez stocker toutes vos données utilisateur sur le domaine A et référencer ces données en envoyant des demandes à l'iframe du domaine A.

Ainsi, les domaines B, C, etc. peuvent injecter l'iframe et lui envoyer des demandes pour stocker et accéder aux données souhaitées. Le domaine A devient le hub de toutes les données partagées.

Avec une liste blanche de domaines à l'intérieur du domaine A, vous pouvez vous assurer que seuls vos sites dépendants peuvent accéder aux données du domaine A.

L'astuce consiste à avoir le code à l'intérieur de l'iframe sur le domaine A qui est capable de reconnaître les données qui sont demandées. Le fichier README du module NPM ci-dessus approfondit la procédure.

J'espère que cela t'aides!

jmealy
la source
-4

Lire Cookie dansWeb Api

var cookie = actionContext.Request.Headers.GetCookies("newhbsslv1");


                    Logger.Log("Cookie  " + cookie, LoggerLevel.Info);
                    Logger.Log("Cookie count  " + cookie.Count, LoggerLevel.Info);

                    if (cookie != null && cookie.Count > 0)
                    {
                        Logger.Log("Befor For  " , LoggerLevel.Info);
                        foreach (var perCookie in cookie[0].Cookies)
                        {
                            Logger.Log("perCookie  " + perCookie, LoggerLevel.Info);

                            if (perCookie.Name == "newhbsslv1")
                            {
                                strToken = perCookie.Value;
                            }
                        }
                    }
user7712621
la source
Cela ne gère pas la question OP de l'utilisation sur deux domaines différents
Niklas Wulff