Pliki cookie między domenami

247

Mam dwie aplikacje WebApp1 i WebApp2 w dwóch różnych domenach.

  1. Ustawiam ciasteczko w WebApp1 w HttpResponse.
  2. Jak odczytać ten sam plik cookie z HttpRequest w WebApp2?

Wiem, że to brzmi dziwnie, ponieważ pliki cookie są specyficzne dla danej domeny i nie możemy uzyskać do nich dostępu z różnych domen; Słyszałem jednak o plikach cookie CROSS-DOMAIN, które można udostępniać w wielu aplikacjach internetowych. Jak wdrożyć ten wymóg przy użyciu plików cookie CROSS-DOMAIN?

Uwaga: próbuję tego z aplikacjami internetowymi J2EE

SundarJavaDeveloper
źródło

Odpowiedzi:

130

Tak, absolutnie możliwe jest uzyskanie ciasteczka z domain1.com przez domain2.com. Miałem ten sam problem z wtyczką społecznościową mojej sieci społecznościowej i po całym dniu badań znalazłem rozwiązanie.

Po pierwsze, po stronie serwera musisz mieć następujące nagłówki:

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

W pliku PHP możesz użyć $_COOKIE[name]

Po drugie, po stronie klienta:

Do żądania ajax należy dołączyć 2 parametry

crossDomain: true
xhrFields: { withCredentials: true }

Przykład:

type: "get",
url: link,
crossDomain: true,
dataType: 'json',
xhrFields: {
  withCredentials: true
}
Ludovic
źródło
6
Lub jeśli nie chcesz filtrować według pochodzenia, po prostu użyj $ _SERVER ['HTTP_ORIGIN'] zamiast *
Joel Teply
1
To jedyne rzeczy, które działały dla mnie. Ponadto * nie zostało zaakceptowane jako pochodzenie, więc potrzebna jest wskazówka @Joela Teply'ego.
Zgadł
4
To nie zadziała, jeśli pliki cookie innych firm są wyłączone (automatyczne w niektórych sytuacjach w przeglądarce). Aby uzyskać więcej informacji, zobacz blog.zok.pw/web/2015/10/21/3rd-party-cookies-in-practice i allannienhuis.com/archives/2013/11/03/ ...
robocat
4
Nie należy używać końcówki Joela, ponieważ jest „w istocie” takie samo jak ustawienie go na „*”, który może otworzyć subtelne luk bezpieczeństwa więc jest zalecane, patrz stackoverflow.com/questions/12001269/...
rogerdpack
5
po której stronie jest serwer?
Nick Manning
127

Jak mówią inni, nie możesz udostępniać plików cookie, ale możesz zrobić coś takiego:

  1. scentralizować wszystkie pliki cookie w jednej domenie, powiedzmy cookiemaker.com
  2. gdy użytkownik zgłosi żądanie do example.com, przekierowujesz go na cookiemaker.com
  3. cookiemaker.com przekierowuje go z powrotem do example.com z potrzebnymi informacjami

Oczywiście nie jest to całkowicie bezpieczne i musisz w tym celu stworzyć wewnętrzny protokół między aplikacjami.

Wreszcie, byłoby bardzo denerwujące dla użytkownika, gdybyś robił coś takiego przy każdym żądaniu, ale nie, jeśli jest to tylko pierwszy.

Ale myślę, że nie ma innego sposobu ...

alcuadrado
źródło
44
Jeśli nie ma innego sposobu, jak działa StackExchange / OpenID?
Hawken,
60
@Hawken StackExchange / OpenID wykonuje ten sam proces, jak opisano powyżej. Zostaniesz przekierowany na inną stronę (SO> SX), potwierdź swoją tożsamość, a następnie z powrotem do SO z potrzebnymi informacjami. Specyfikacja OpenID wyjaśnia więcej, chociaż Wikipedia robi to bardziej wyraźnie .
Nick Q.
1
Wszyscy użytkownicy są zalogowani w cookiemaker.com. I przekierowuje użytkownika do różnych stron za pomocą specjalnej i bezpiecznej wiadomości, która weryfikuje, czy jest on zalogowany i kim jest. To, jak go wdrożyć, zależy od ciebie, istnieją nieskończone możliwości tego. Może możesz użyć tego: jwt.io
alcuadrado
8
@ Andrew_1510 cookiebakerbyłby lepszy ;-)
Richard Turner
1
Oto post z tagiem graficznym, czy to lepsze rozwiązanie ?
shaijut
70

O ile mi wiadomo, pliki cookie są ograniczone przez zasady „tego samego pochodzenia”. Jednak dzięki CORS możesz otrzymywać i wykorzystywać pliki cookie „Server B” w celu ustanowienia trwałej sesji z „Server A” na „Server B”.

Wymaga to jednak niektórych nagłówków na „serwerze B”:

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

I trzeba będzie wysłać flaga „ withCredentials ” na wszystkich wniosków „Serwer A” (Ex: xhr.withCredentials = true;)

Możesz przeczytać o tym tutaj:

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

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

Vitae Aliquam
źródło
11
To nie będzie działać dla niektórych użytkowników, ponieważ pliki cookie CORS nie będą działać, jeśli pliki cookie innych firm są wyłączone, np. Safari domyślnie np . Ustawienia Mozilli . Google więcej przykładów i artykuł o tym, dlaczego Facebook nie używa plików cookie stron trzecich.
robocat
1
Czy wymiana stosu / openID używa CORS?
RayLoveless
1
FWIW Właśnie przetestowałem normalny CORS z Poświadczeniami XHR i działał on na FF / Safari / Chrome ... chociaż nie
wątpiłbym,
30

Nie ma czegoś takiego jak pliki cookie między domenami. Możesz udostępnić plik cookie pomiędzy foo.example.comi, bar.example.comale nigdy pomiędzy, example.comi example2.comto ze względów bezpieczeństwa.

Darin Dimitrov
źródło
1
Cześć, dziękuję za odpowiedź, czy możesz dodać więcej przejrzystości w części konfiguracyjnej, jak utworzyć / skonfigurować domenę i subdomenę w środowisku j2ee ???
SundarJavaDeveloper
1
To pytanie jest bardziej dostosowane do serverfault.com, gdzie uzyskasz odpowiedzi od ekspertów w tej dziedzinie.
Darin Dimitrov
Cześć, próbowałem mieć dwie aplikacje WebApp.domain.com ==> tutaj dodaję plik cookie w następujący sposób: Cookie cookie = new Cookie („namedCookie”, „test”); cookie.setDomain („. domain.com”); response.addCookie (cookie); WebApp1.domain.com ==> Tutaj próbowałem uzyskać dostęp do pliku cookie w następujący sposób, ale nie mogę uzyskać dostępu do Cookie [] cks = request.getCookies (); for (int i = 0; i <cks.length; i ++) {out.print („cookie znaleziono” + cks [i] .getValue ()); } Masz jakiś pomysł na ten temat?
SundarJavaDeveloper
2
często powtarzane, ale nieprawdziwe, zobacz moją odpowiedź poniżej lub tutaj stackoverflow.com/questions/16186645/…
Raphael Jeger 24.04.13
4
Jak udostępniać pliki cookie między foo.example.comi bar.example.com?
Jeff Tian,
24

Najmądrzejszym rozwiązaniem jest podążanie w tym kierunku drogą Facebooka. Skąd Facebook wie, kim jesteś, kiedy odwiedzasz dowolną domenę? To jest naprawdę bardzo proste :

Przycisk Lubię to pozwala Facebookowi śledzić wszystkich odwiedzających witrynę zewnętrzną, bez względu na to, czy klikną ją, czy nie. Facebook może to zrobić, ponieważ do wyświetlenia przycisku używają elementu iframe . Ramka iframe jest czymś w rodzaju osadzonego okna przeglądarki na stronie. Różnica między użyciem elementu iframe a prostym obrazem przycisku polega na tym, że element iframe zawiera pełną stronę internetową - z Facebooka . Na tej stronie niewiele się dzieje, z wyjątkiem przycisku i informacji o tym, ile osób polubiło bieżącą stronę.

Więc kiedy zobaczysz przycisk „Lubię to” na cnn.com, faktycznie odwiedzasz jednocześnie stronę na Facebooku. Dzięki temu Facebook może odczytać plik cookie na twoim komputerze, który utworzył podczas ostatniego logowania na Facebooku.

Podstawową zasadą bezpieczeństwa w każdej przeglądarce jest to, że tylko strona internetowa, która utworzyła plik cookie, może go później przeczytać. I to jest zaleta iframe: pozwala Facebookowi czytać twoje ciasteczka na Facebooku, nawet gdy odwiedzasz inną stronę internetową. W ten sposób rozpoznają cię na cnn.com i wyświetlają tam znajomych.

Źródło:

Morteza Shahriari Nia
źródło
6
Myślę, że iframe rzadko klasyfikuje się jako najlepszy lub najmądrzejszy sposób na zrobienie czegokolwiek ... ale jest to najłatwiejszy.
Orun
13

Rób to, co robi Google. Utwórz plik PHP, który ustawia ciasteczko we wszystkich 3 domenach. Następnie w domenie, w której ma zostać ustawiony motyw, utwórz plik HTML, który załaduje plik PHP, który ustawia plik cookie w pozostałych 2 domenach. Przykład:

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

Następnie dodaj wywołanie zwrotne na znaczniku body. Dokument zostanie załadowany tylko wtedy, gdy obrazy zostaną w pełni załadowane, czyli gdy pliki cookie zostaną ustawione w pozostałych 2 domenach. Oddzwonienie przy obciążeniu:

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

setcookie.php

Ustawiamy pliki cookie w innych domenach za pomocą pliku PHP takiego:

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

Teraz pliki cookie są ustawione w trzech domenach.

Hossain Khademian
źródło
2
Nie działa to, jeśli włączona jest funkcja „Blokuj pliki cookie stron trzecich”.
Jens
11

Nie można udostępniać plików cookie między domenami. Możesz jednak zezwolić na dostęp do wszystkich subdomen. Aby umożliwić wszystkim subdomenom example.comdostęp, ustaw domenę na .example.com.

Nie można jednak otherexample.comuzyskać dostępu do example.complików cookie.

Daniel Egeberg
źródło
27
dlaczego więc pojawiają się .google.compliki cookie podczas przeglądania YouTube?
Hawken,
20
Tagi Google Analytics. Te pliki cookie pochodzą z google.com, a nie z youtube.com.
Entendu
8

Możesz spróbować przenieść plik cookie val do innej domeny za pomocą tagu obrazu.

Twój przebieg może być różny, gdy próbujesz to zrobić, ponieważ niektóre przeglądarki wymagają posiadania odpowiednich zasad P3P w domenie WebApp2 lub przeglądarka odrzuci ciasteczko.

Jeśli spojrzysz na zasady plus.google.com p3p, zobaczysz, że ich zasady to:

CP = „To nie jest zasada P3P! Więcej informacji można znaleźć na stronie http://www.google.com/support/accounts/bin/answer.py?hl=pl&answer=151657 ”.

to jest zasada, której używają dla swoich przycisków +1 do tych żądań między domenami.

Kolejnym ostrzeżeniem jest to, że jeśli korzystasz z https, upewnij się, że tag obrazu wskazuje adres https, w przeciwnym razie pliki cookie nie zostaną ustawione.

Bryan Focht
źródło
2
Chcesz się trochę rozwinąć?
często
5

Na stronie nfriedly.com jest dobry przegląd tego, jak robi to Facebook

Istnieje również odcisk palca przeglądarki, który nie jest tym samym co plik cookie, ale służy podobnemu celowi, ponieważ pomaga zidentyfikować użytkownika z pewnym stopniem pewności. Jest tutaj post na temat przepełnienia stosu, który odwołuje się do jednej metody pobierania odcisków palców

byZero
źródło
1

Aby uzyskać pliki cookie, można użyć niewidocznych elementów iframe. Załóżmy, że istnieją dwie domeny: a.com i b.com. Do index.html domeny a.com można dodać (zauważ wysokość = 0 szerokość = 0):

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

W ten sposób Twoja witryna otrzyma pliki cookie b.com, zakładając, że http://b.com ustawia pliki cookie.

Następną rzeczą byłoby manipulowanie stroną wewnątrz elementu iframe za pomocą JavaScript. Operacje wewnątrz iframe mogą stać się wyzwaniem, jeśli nie jest się właścicielem drugiej domeny. Ale w przypadku dostępu do obu domen odsyłających na odpowiednią stronę internetową pod adresem src iframe należy podać pliki cookie, które chcieliby uzyskać.

Wadym Tyemirow
źródło
5
Tylko ostrzeżenie: istnieją pewne poważne problemy z plikami cookie w elementach iframe w przeglądarce Safari. Najwyraźniej nie działają one w wielu domenach.
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

Dołącz początek interfejsu użytkownika i ustaw wartość Zezwalaj na media

<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>
użytkownik7712621
źródło
1

Stworzyłem moduł NPM, który pozwala udostępniać lokalnie przechowywane dane między domenami: https://www.npmjs.com/package/cookie-toss

Korzystając z elementu iframe hostowanego w domenie A, można przechowywać wszystkie dane użytkownika w domenie A i odwoływać się do tych danych, wysyłając żądania do elementu iframe domeny A.

Domeny B, C itd. Mogą zatem wstrzykiwać ramkę iframe i wysyłać do niej żądania przechowywania i uzyskiwania dostępu do żądanych danych. Domena A staje się centrum wszystkich udostępnianych danych.

Dzięki białej liście domen w domenie A możesz mieć pewność, że tylko Twoje witryny zależne będą miały dostęp do danych w domenie A.

Sztuką jest umieszczenie kodu w elemencie iframe w domenie A, który jest w stanie rozpoznać, które dane są wymagane. Plik README w powyższym module NPM jest bardziej szczegółowo opisany w procedurze.

Mam nadzieję że to pomoże!

jmealy
źródło
-4

Czytać Cookie wWeb 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;
                            }
                        }
                    }
użytkownik7712621
źródło
Nie rozwiązuje to problemu OP dotyczącego używania w dwóch różnych domenach
Niklas Wulff