Cookies de dominio cruzado

247

Tengo dos aplicaciones web WebApp1 y WebApp2 en dos dominios diferentes.

  1. Estoy configurando una cookie en WebApp1 en HttpResponse.
  2. ¿Cómo leer la misma cookie de HttpRequest en WebApp2?

Sé que suena extraño porque las cookies son específicas de un dominio determinado y no podemos acceder a ellas desde diferentes dominios; Sin embargo, he oído hablar de cookies CROSS-DOMAIN que se pueden compartir en varias aplicaciones web. ¿Cómo implementar este requisito usando cookies de CROSS-DOMAIN?

Nota: Estoy intentando esto con aplicaciones web J2EE

SundarJavaDeveloper
fuente

Respuestas:

130

Sí, es absolutamente posible obtener la cookie de domain1.com por domain2.com. Tuve el mismo problema para un complemento social de mi red social, y después de un día de investigación encontré la solución.

Primero, en el lado del servidor necesita tener los siguientes encabezados:

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

Dentro del archivo PHP puedes usar $_COOKIE[name]

En segundo lugar, en el lado del cliente:

Dentro de su solicitud ajax, debe incluir 2 parámetros

crossDomain: true
xhrFields: { withCredentials: true }

Ejemplo:

type: "get",
url: link,
crossDomain: true,
dataType: 'json',
xhrFields: {
  withCredentials: true
}
Ludovic
fuente
66
O si no desea filtrar por origen, simplemente use $ _SERVER ['HTTP_ORIGIN'] en lugar de *
Joel Teply
1
Esto es lo único que me funcionó. Además, * no fue aceptado como origen, por lo que se necesita la sugerencia de @Joel Teply.
Adivinado
44
Esto no funcionará si las cookies de terceros están deshabilitadas (automático para algunas situaciones del navegador). Consulte blog.zok.pw/web/2015/10/21/3rd-party-cookies-in-practice y allannienhuis.com/archives/2013/11/03/… para obtener más información.
robocat
44
No use la sugerencia de Joel, porque es "en esencia" lo mismo que establecerla en "*", lo que puede abrir sutiles agujeros de seguridad, por lo que no se
recomienda
55
en el lado del servidor de qué dominio?
Nick Manning
127

Como dicen otras personas, no puedes compartir cookies, pero puedes hacer algo como esto:

  1. centralice todas las cookies en un solo dominio, digamos cookiemaker.com
  2. cuando el usuario realiza una solicitud a example.com, lo redirige a cookiemaker.com
  3. cookiemaker.com lo redirige a example.com con la información que necesita

Por supuesto, no es completamente seguro, y tienes que crear algún tipo de protocolo interno entre tus aplicaciones para hacerlo.

Por último, sería muy molesto para el usuario si haces algo así en cada solicitud, pero no si es solo la primera.

Pero creo que no hay otra manera ...

alcuadrado
fuente
44
Si no hay otra forma, ¿cómo funciona StackExchange / OpenID?
Hawken
6060
@Hawken StackExchange / OpenID sigue el mismo proceso que el descrito anteriormente. Se lo dirige a un sitio diferente (SO> SX), confirma su identidad y luego se lo dirige de regreso a SO con la información que necesita. La especificación OpenID explica más, aunque Wikipedia lo hace más claramente .
Nick Q.
1
Todos los usuarios han iniciado sesión en cookiemaker.com en realidad. Y redirige al usuario a los diferentes sitios con un mensaje especial y seguro que verifica que están conectados y quiénes son. Cómo implementarlo depende de usted, hay infinitas formas de hacerlo. Tal vez pueda usar esto: jwt.io
alcuadrado
8
@ Andrew_1510 cookiebakersería mejor ;-)
Richard Turner
1
Aquí está la publicación con etiqueta de imagen, ¿es esa una mejor solución ?
shaijut
70

Hasta donde yo sé, las cookies están limitadas por la política del "mismo origen". Sin embargo, con CORS puede recibir y usar las cookies del "Servidor B" para establecer una sesión persistente del "Servidor A" en el "Servidor B".

Aunque, esto requiere algunos encabezados en el "Servidor B":

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

Y usted tendrá que enviar la bandera " withCredentials " en todas las peticiones "A" del servidor (por ejemplo: xhr.withCredentials = true;)

Usted puede leer sobre ello aquí:

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

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

Vitae Aliquam
fuente
11
Esto no funcionará para algunos usuarios porque las cookies CORS no funcionarán si las cookies de terceros están desactivadas, por ejemplo, Safari de forma predeterminada, por ejemplo, la configuración de Mozilla . Busque más ejemplos en Google y un artículo sobre por qué Facebook no utiliza cookies de terceros.
robocat
1
¿El intercambio de pila / openID usa CORS?
RayLoveless
1
FWIW Acabo de probar un CORS normal con credenciales XHR y funcionó en FF / Safari / Chrome ... aunque no dudaría de que Facebook / Google use esquemas más sofisticados
rogerdpack
30

No existen las cookies de dominio cruzado. Puede compartir una cookie entre foo.example.comy bar.example.compero nunca entre example.comy example2.comy eso es por razones de seguridad.

Darin Dimitrov
fuente
1
Hola, gracias por la respuesta, ¿puedes agregar más claridad en la parte de configuración, cómo crear / configurar el dominio y el subdominio en el entorno j2ee?
SundarJavaDeveloper
1
Esta es una pregunta que está más adaptada a serverfault.com donde obtendrá respuestas de expertos en el dominio.
Darin Dimitrov
Hola, intenté tener dos aplicaciones web WebApp.domain.com ==> aquí agrego la cookie en respose de la siguiente manera: Cookie cookie = nueva Cookie ("namedCookie", "test"); cookie.setDomain (". domain.com"); response.addCookie (cookie); WebApp1.domain.com ==> Aquí intenté acceder a la cookie de la siguiente manera, pero no puedo acceder a Cookie [] cks = request.getCookies (); for (int i = 0; i <cks.length; i ++) {out.print ("cookie encontrada" + cks [i] .getValue ()); } ¿Alguna idea sobre esto?
SundarJavaDeveloper
2
a menudo repetido pero no es cierto, vea mi respuesta a continuación o aquí stackoverflow.com/questions/16186645/…
Raphael Jeger
44
¿Cómo compartir cookies entre foo.example.comy bar.example.com?
Jeff Tian
24

La solución más inteligente es seguir el camino de Facebook en esto. ¿Cómo sabe Facebook quién eres cuando visitas un dominio? En realidad es muy simple :

El botón Me gusta en realidad le permite a Facebook rastrear a todos los visitantes del sitio externo, sin importar si hacen clic o no. Facebook puede hacer eso porque usan un iframe para mostrar el botón. Un iframe es algo así como una ventana de navegador incrustada dentro de una página. La diferencia entre usar un iframe y una imagen simple para el botón es que el iframe contiene una página web completa, de Facebook . No está sucediendo mucho en esta página, excepto por el botón y la información sobre a cuántas personas les ha gustado la página actual.

Entonces, cuando ve un botón de me gusta en cnn.com, en realidad está visitando una página de Facebook al mismo tiempo. Eso le permite a Facebook leer una cookie en su computadora, que ha creado la última vez que inició sesión en Facebook.

Una regla de seguridad fundamental en cada navegador es que solo el sitio web que ha creado una cookie puede leerla más adelante. Y esa es la ventaja del iframe: le permite a Facebook leer su cookie de Facebook incluso cuando está visitando un sitio web diferente. Así es como te reconocen en cnn.com y muestran a tus amigos allí.

Fuente:

Morteza Shahriari Nia
fuente
66
Creo que un iframe raramente clasificaría como la mejor o la forma más inteligente de hacer algo ... pero es la más fácil.
Orun
13

Haz lo que Google está haciendo. Cree un archivo PHP que establezca la cookie en los 3 dominios. Luego, en el dominio donde se establecerá el tema, cree un archivo HTML que cargue el archivo PHP que establece la cookie en los otros 2 dominios. Ejemplo:

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

Luego agregue una devolución de llamada de carga en la etiqueta del cuerpo. El documento solo se cargará cuando las imágenes se carguen por completo, es decir, cuando las cookies se configuran en los otros 2 dominios. Devolución de llamada de carga:

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

setcookie.php

Configuramos las cookies en los otros dominios usando un archivo PHP como este:

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

Ahora las cookies están configuradas en los tres dominios.

Hossain Khademian
fuente
2
Esto no funciona si la función 'Bloquear cookies de terceros' está habilitada.
Jens
11

No puede compartir cookies entre dominios. Sin embargo, puede permitir que todos los subdominios tengan acceso. Para permitir que todos los subdominios example.comtengan acceso, establezca el dominio en .example.com.

Sin embargo , no es posible dar otherexample.comacceso a example.comlas cookies de.

Daniel Egeberg
fuente
27
¿Cómo es que las .google.comcookies aparecen cuando navegas a YouTube?
Hawken
20
Etiquetas de Google analytics. Esas cookies provienen de google.com, no de youtube.com.
Entendu
8

Puede intentar empujar la cookie val a otro dominio utilizando una etiqueta de imagen.

Su millaje puede variar cuando intente hacer esto porque algunos navegadores requieren que tenga una Política P3P adecuada en el dominio de WebApp2 o el navegador rechazará la cookie.

Si observa la política p3p de plus.google.com, verá que su política es:

CP = "¡Esta no es una política P3P! Consulte http://www.google.com/support/accounts/bin/answer.py?hl=es&answer=151657 para obtener más información".

esa es la política que usan para sus botones de +1 a estas solicitudes de dominio cruzado.

Otra advertencia es que si está en https, asegúrese de que la etiqueta de la imagen apunte a una dirección https; de lo contrario, las cookies no se establecerán.

Bryan Focht
fuente
2
¿Te importa elaborar un poco?
frecuente
5

Hay una descripción general decente de cómo Facebook lo hace aquí en nfriedly.com

También hay huellas digitales del navegador, que no es lo mismo que una cookie, pero tiene el mismo propósito, ya que le ayuda a identificar a un usuario con un cierto grado de certeza. Hay una publicación aquí en Stack Overflow que hace referencia a un método de huellas digitales

por Zero
fuente
1

Uno puede usar iframes invisibles para obtener las cookies. Digamos que hay dos dominios, a.com y b.com. Para el index.html del dominio a.com se puede agregar (observe la altura = 0 ancho = 0):

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

De esa forma, su sitio web recibirá cookies de b.com, suponiendo que http://b.com las configure.

Lo siguiente sería manipular el sitio dentro del iframe a través de JavaScript. Las operaciones dentro del iframe pueden convertirse en un desafío si uno no posee el segundo dominio. Pero en caso de tener acceso a ambos dominios, la página web correcta en el src de iframe debería proporcionar las cookies que le gustaría obtener.

Vadym Tyemirov
fuente
55
Solo una advertencia: hay algunos problemas serios con las cookies en iframes en Safari. Aparentemente no funcionan entre dominios.
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

Incluya el origen de la IU y establezca Permitir Crentiales en verdadero

<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>
usuario7712621
fuente
1

Creé un módulo NPM, que le permite compartir datos almacenados localmente entre dominios: https://www.npmjs.com/package/cookie-toss

Al usar un iframe alojado en el Dominio A, puede almacenar todos sus datos de usuario en el Dominio A y hacer referencia a esos datos publicando solicitudes en el iframe del Dominio A.

Por lo tanto, los dominios B, C, etc. pueden inyectar el iframe y publicar solicitudes para almacenar y acceder a los datos deseados. El dominio A se convierte en el centro de todos los datos compartidos.

Con una lista blanca de dominios dentro del Dominio A, puede asegurarse de que solo sus sitios dependientes puedan acceder a los datos en el Dominio A.

El truco es tener el código dentro del iframe en el Dominio A que puede reconocer qué datos se solicitan. El archivo README en el módulo NPM anterior profundiza en el procedimiento.

¡Espero que esto ayude!

jmealy
fuente
-4

Leer Cookie enWeb 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;
                            }
                        }
                    }
usuario7712621
fuente
Esto no maneja la cuestión OP de usar en dos dominios diferentes
Niklas Wulff