Domainübergreifende Cookies

246

Ich habe zwei Webapps WebApp1 und WebApp2 in zwei verschiedenen Domänen.

  1. Ich setze ein Cookie in WebApp1 in der HttpResponse.
  2. Wie lese ich das gleiche Cookie von HttpRequest in WebApp2?

Ich weiß, dass es seltsam klingt, weil Cookies für eine bestimmte Domain spezifisch sind und wir nicht von verschiedenen Domains aus darauf zugreifen können. Ich habe jedoch von CROSS-DOMAIN-Cookies gehört, die von mehreren Webanwendungen gemeinsam genutzt werden können. Wie kann diese Anforderung mithilfe von CROSS-DOMAIN-Cookies implementiert werden?

Hinweis: Ich versuche dies mit J2EE-Webanwendungen

SundarJavaDeveloper
quelle

Antworten:

130

Ja, es ist absolut möglich, das Cookie von domain1.com über domain2.com abzurufen. Ich hatte das gleiche Problem mit einem sozialen Plugin meines sozialen Netzwerks und fand nach einem Tag der Recherche die Lösung.

Zunächst müssen Sie auf der Serverseite die folgenden Header haben:

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, *");

Innerhalb der PHP-Datei können Sie verwenden $_COOKIE[name]

Zweitens auf der Client-Seite:

In Ihre Ajax-Anfrage müssen Sie 2 Parameter aufnehmen

crossDomain: true
xhrFields: { withCredentials: true }

Beispiel:

type: "get",
url: link,
crossDomain: true,
dataType: 'json',
xhrFields: {
  withCredentials: true
}
Ludovic
quelle
6
Oder wenn Sie nicht nach Ursprung filtern möchten, verwenden Sie einfach $ _SERVER ['HTTP_ORIGIN'] anstelle von *
Joel Teply
1
Dies ist das einzige, was für mich funktioniert hat. Außerdem wurde * nicht als Ursprung akzeptiert, daher wird der Tipp von @Joel Teply benötigt.
Vermutlich
4
Dies funktioniert nicht, wenn Cookies von Drittanbietern deaktiviert sind (in einigen Browsersituationen automatisch). Weitere Informationen finden Sie unter blog.zok.pw/web/2015/10/21/3rd-party-cookies-in-practice und allbrithuis.com/archives/2013/11/03/… .
Robocat
4
Verwenden Sie Joels Tipp nicht, da er "im Wesentlichen" mit dem Setzen auf "*" identisch
Daher
5
Auf der Serverseite welcher Domain?
Nick Manning
127

Wie andere Leute sagen, können Sie keine Cookies teilen, aber Sie könnten Folgendes tun:

  1. Zentralisieren Sie alle Cookies in einer einzigen Domain, sagen wir cookiemaker.com
  2. Wenn der Benutzer eine Anfrage an example.com stellt, leiten Sie ihn an cookiemaker.com weiter
  3. cookiemaker.com leitet ihn mit den benötigten Informationen zurück zu example.com

Natürlich ist es nicht vollständig sicher, und Sie müssen dazu eine Art internes Protokoll zwischen Ihren Apps erstellen.

Schließlich wäre es für den Benutzer sehr ärgerlich, wenn Sie bei jeder Anfrage so etwas tun, aber nicht, wenn es nur die erste ist.

Aber ich denke, es gibt keinen anderen Weg ...

alcuadrado
quelle
44
Wenn es keinen anderen Weg gibt, wie funktioniert dann StackExchange / OpenID?
Hawken
60
@ Hawken StackExchange / OpenID folgt dem oben beschriebenen Vorgang. Sie werden zu einer anderen Site (SO> SX) weitergeleitet, bestätigen Ihre Identität und werden dann mit den benötigten Informationen zu SO zurückgeleitet. Die OpenID-Spezifikation erklärt mehr, obwohl Wikipedia dies klarer macht .
Nick Q.
1
Alle Benutzer sind tatsächlich in cookiemaker.com angemeldet. Außerdem wird der Benutzer mit einer speziellen und sicheren Nachricht zu den verschiedenen Sites weitergeleitet, die bestätigt, ob er angemeldet ist und wer er ist. Wie Sie es implementieren, liegt bei Ihnen. Es gibt unendlich viele Möglichkeiten, dies zu tun. Vielleicht können Sie dies verwenden: jwt.io
alcuadrado
8
@ Andrew_1510 cookiebakerwäre besser ;-)
Richard Turner
1
Hier ist ein Beitrag mit Bild-Tag. Ist das eine bessere Lösung ?
Shaijut
70

Soweit ich weiß, sind Cookies durch die Richtlinie "gleichen Ursprungs" beschränkt. Mit CORS können Sie jedoch die Cookies "Server B" empfangen und verwenden, um eine dauerhafte Sitzung von "Server A" auf "Server B" einzurichten.

Dies erfordert jedoch einige Header auf "Server B":

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

Und Sie müssen das Flag " withCredentials " für alle "Server A" -Anfragen senden (Beispiel:xhr.withCredentials = true; )

Sie können hier darüber lesen:

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

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

Lebenslauf Aliquam
quelle
11
Dies funktioniert bei einigen Benutzern nicht, da CORS-Cookies nicht funktionieren, wenn Cookies von Drittanbietern deaktiviert sind, z. B. standardmäßig Safari, z . B. Mozilla-Einstellungen . Google weitere Beispiele und einen Artikel darüber, warum Facebook keine Cookies von Drittanbietern verwendet.
Robocat
1
Verwendet Stack Exchange / OpenID CORS?
RayLoveless
1
FWIW Ich habe gerade ein normales CORS mit Credentials XHR getestet und es funktionierte unter FF / Safari / Chrome ... obwohl ich nicht bezweifeln würde, dass Facebook / Google anspruchsvollere Schemata verwenden
Rogerdpack
29

Es gibt keine domänenübergreifenden Cookies. Sie könnten ein Cookie zwischen foo.example.comund bar.example.comaber niemals zwischen example.comund teilen, example2.comund das aus Sicherheitsgründen.

Darin Dimitrov
quelle
1
Hallo, danke für die Antwort. Kannst du bitte mehr Klarheit über den Konfigurationsteil hinzufügen, wie man eine Domain und eine Subdomain in einer j2ee-Umgebung erstellt / konfiguriert?
SundarJavaDeveloper
1
Diese Frage ist eher an serverfault.com angepasst, wo Sie Antworten von Experten auf diesem Gebiet erhalten.
Darin Dimitrov
Hallo, ich habe versucht, zwei Webapps zu haben. WebApp.domain.com ==> hier füge ich Cookies wie folgt hinzu: Cookie cookie = neues Cookie ("namedCookie", "test"); cookie.setDomain (". domain.com"); response.addCookie (Cookie); WebApp1.domain.com ==> Hier habe ich versucht, wie folgt auf das Cookie zuzugreifen, kann aber nicht auf Cookie zugreifen [] cks = request.getCookies (); für (int i = 0; i <cks.length; i ++) {out.print ("Cookie gefunden" + cks [i] .getValue ()); } Irgendeine Idee dazu?
SundarJavaDeveloper
2
oft wiederholt, aber nicht wahr, siehe meine Antwort unten oder hier stackoverflow.com/questions/16186645/…
Raphael Jeger
4
Wie teile ich Cookies zwischen foo.example.comund bar.example.com?
Jeff Tian
24

Die klügste Lösung besteht darin, den Weg von Facebook zu beschreiten. Woher weiß Facebook, wer Sie sind, wenn Sie eine Domain besuchen? Es ist eigentlich sehr einfach :

Über die Schaltfläche "Gefällt mir" kann Facebook tatsächlich alle Besucher der externen Website verfolgen, unabhängig davon, ob sie darauf klicken oder nicht. Facebook kann dies tun, weil sie einen Iframe verwenden , um die Schaltfläche anzuzeigen. Ein Iframe ist so etwas wie ein eingebettetes Browserfenster innerhalb einer Seite. Der Unterschied zwischen der Verwendung eines Iframes und eines einfachen Bildes für die Schaltfläche besteht darin, dass der Iframe eine vollständige Webseite enthält - von Facebook . Auf dieser Seite ist nicht viel los, außer der Schaltfläche und den Informationen darüber, wie vielen Personen die aktuelle Seite gefallen hat.

Wenn Sie also auf cnn.com einen Like-Button sehen, besuchen Sie gleichzeitig eine Facebook-Seite. Auf diese Weise kann Facebook ein Cookie auf Ihrem Computer lesen, das beim letzten Anmelden bei Facebook erstellt wurde.

Eine grundlegende Sicherheitsregel in jedem Browser ist, dass nur die Website, die ein Cookie erstellt hat, es später lesen kann. Und das ist der Vorteil des iframe: Facebook kann Ihren Facebook-Cookie auch dann lesen, wenn Sie eine andere Website besuchen. So erkennen sie dich auf cnn.com und zeigen deine Freunde dort an.

Quelle:

Morteza Shahriari Nia
quelle
6
Ich denke, ein Iframe würde selten als der beste oder klügste Weg eingestuft, etwas zu tun. Aber es ist der einfachste.
Orun
13

Tun Sie, was Google tut. Erstellen Sie eine PHP-Datei, die das Cookie für alle drei Domänen setzt. Erstellen Sie dann in der Domäne, in der das Thema festgelegt werden soll, eine HTML-Datei, die die PHP-Datei lädt, die Cookies auf die anderen beiden Domänen setzt. Beispiel:

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

Fügen Sie dann einen Onload-Rückruf für das Body-Tag hinzu. Das Dokument wird nur geladen, wenn die Bilder vollständig geladen sind, dh wenn Cookies auf den anderen beiden Domänen gesetzt werden. Onload-Rückruf:

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

setcookie.php

Wir setzen die Cookies auf den anderen Domains mit einer PHP-Datei wie folgt:

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

Jetzt werden Cookies auf die drei Domains gesetzt.

Hossain Khademian
quelle
2
Dies funktioniert nicht, wenn die Funktion "Cookies von Drittanbietern blockieren" aktiviert ist.
Jens
11

Sie können Cookies nicht domänenübergreifend freigeben. Sie können jedoch allen Subdomains Zugriff gewähren. Stellen Sie example.comdie Domäne auf ein, damit alle Subdomains Zugriff haben .example.com.

Es ist jedoch nicht möglich, otherexample.comZugriff auf example.comdie Cookies zu gewähren .

Daniel Egeberg
quelle
27
Wie kommt es .google.com, dass beim Surfen auf YouTube Cookies angezeigt werden?
Hawken
20
Google Analytics-Tags. Diese Cookies stammen von google.com, nicht von youtube.com.
Entendu
8

Sie können versuchen, das Cookie-Val mithilfe eines Image-Tags in eine andere Domain zu verschieben.

Ihr Kilometerstand kann variieren, wenn Sie dies versuchen, da für einige Browser eine ordnungsgemäße P3P-Richtlinie für die WebApp2-Domäne erforderlich ist. Andernfalls lehnt der Browser das Cookie ab.

Wenn Sie sich die p3p-Richtlinie von plus.google.com ansehen, werden Sie feststellen, dass ihre Richtlinie lautet:

CP = "Dies ist keine P3P-Richtlinie! Weitere Informationen finden Sie unter http://www.google.com/support/accounts/bin/answer.py?hl=de&answer=151657 ."

Dies ist die Richtlinie, die sie für ihre + 1-Schaltflächen für diese domänenübergreifenden Anforderungen verwenden.

Eine weitere Warnung ist, dass Sie bei https sicherstellen müssen, dass das Image-Tag auf eine https-Adresse verweist, da sonst keine Cookies gesetzt werden.

Bryan Focht
quelle
2
Möchtest du etwas näher darauf eingehen?
häufig
1

Man kann unsichtbare Iframes verwenden, um die Cookies zu erhalten. Angenommen, es gibt zwei Domains, a.com und b.com. Für die index.html der Domain a.com kann man hinzufügen (Höhe beachten = 0 Breite = 0):

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

Auf diese Weise erhält Ihre Website b.com-Cookies, sofern http://b.com die Cookies setzt.

Das nächste wäre, die Site innerhalb des Iframes über JavaScript zu manipulieren. Die Operationen in iframe können zu einer Herausforderung werden, wenn man die zweite Domain nicht besitzt. Wenn Sie jedoch Zugriff auf beide Domains haben, sollten Sie auf die richtige Webseite im src von iframe verweisen und die Cookies erhalten, die Sie erhalten möchten.

Vadym Tyemirov
quelle
5
Nur eine Warnung: Es gibt einige schwerwiegende Probleme mit Cookies in iframes auf Safari. Sie arbeiten anscheinend nicht domänenübergreifend.
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

Schließen Sie den UI-Ursprung ein und setzen Sie Allow Crentials auf 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
quelle
1

Ich habe ein NPM-Modul erstellt, mit dem Sie lokal gespeicherte Daten domänenübergreifend austauschen können: https://www.npmjs.com/package/cookie-toss

Mithilfe eines in Domäne A gehosteten Iframes können Sie alle Ihre Benutzerdaten in Domäne A speichern und auf diese Daten verweisen, indem Sie Anforderungen an den Iframe in Domäne A senden.

Somit können die Domänen B, C usw. den Iframe einfügen und Anforderungen an ihn senden, um die gewünschten Daten zu speichern und darauf zuzugreifen. Domäne A wird zum Hub für alle gemeinsam genutzten Daten.

Mit einer Domain-Whitelist innerhalb von Domain A können Sie sicherstellen, dass nur Ihre abhängigen Sites auf die Daten in Domain A zugreifen können.

Der Trick besteht darin, den Code im Iframe in Domäne A zu haben, der erkennen kann, welche Daten angefordert werden. Die README-Datei im obigen NPM-Modul geht ausführlicher auf die Prozedur ein.

Hoffe das hilft!

jmealy
quelle
-4

Lesen Sie Cookie einWeb 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
quelle
Dies behandelt nicht die OP-Frage der Verwendung auf zwei verschiedenen Domänen
Niklas Wulff