Cookies entre domínios

247

Eu tenho dois webapps WebApp1 e WebApp2 em dois domínios diferentes.

  1. Estou configurando um cookie no WebApp1 no HttpResponse.
  2. Como ler o mesmo cookie do HttpRequest no WebApp2?

Sei que parece estranho porque os cookies são específicos para um determinado domínio e não podemos acessá-los de domínios diferentes; No entanto, ouvi falar de cookies CROSS-DOMAIN que podem ser compartilhados em vários aplicativos da web. Como implementar esse requisito usando cookies CROSS-DOMAIN?

Nota: Estou tentando isso com os aplicativos da web J2EE

SundarJavaDeveloper
fonte

Respostas:

130

Sim, é absolutamente possível obter o cookie de domain1.com por domain2.com. Eu tive o mesmo problema em um plug-in social da minha rede social e, depois de um dia de pesquisa, encontrei a solução.

Primeiro, no lado do servidor, você precisa dos seguintes cabeçalhos:

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 do arquivo PHP você pode usar $_COOKIE[name]

Segundo, no lado do cliente:

Na sua solicitação ajax, você precisa incluir 2 parâmetros

crossDomain: true
xhrFields: { withCredentials: true }

Exemplo:

type: "get",
url: link,
crossDomain: true,
dataType: 'json',
xhrFields: {
  withCredentials: true
}
Ludovic
fonte
6
Ou, se você não deseja filtrar pela origem, use $ _SERVER ['HTTP_ORIGIN'] em vez de * #
Joel Teply
1
Esta é a única coisa que funcionou para mim. Além disso, * não foi aceito como origem, portanto, a dica de @Joel Teply é necessária.
Adivinhou
4
Isso não funcionará se os cookies de terceiros estiverem desativados (automático para algumas situações do navegador). Consulte blog.zok.pw/web/2015/10/21/3rd-party-cookies-in-practice e allannienhuis.com/archives/2013/11/03/… para obter mais informações.
robocat
4
Não use a ponta de Joel, porque é "em essência" o mesmo que defini-lo como "*" que pode abrir buracos na segurança sutis assim está desanimado, veja stackoverflow.com/questions/12001269/...
rogerdpack
5
no lado do servidor de qual domínio?
Nick Manning
127

Como outras pessoas dizem, você não pode compartilhar cookies, mas pode fazer algo assim:

  1. centralizar todos os cookies em um único domínio, digamos cookiemaker.com
  2. quando o usuário faz uma solicitação para example.com, você o redireciona para cookiemaker.com
  3. O cookiemaker.com o redireciona de volta para example.com com as informações necessárias

Claro, não é completamente seguro, e você precisa criar algum tipo de protocolo interno entre seus aplicativos para fazer isso.

Por fim, seria muito chato para o usuário se você fizer algo assim em todas as solicitações, mas não se for apenas a primeira.

Mas acho que não tem outro jeito ...

alcuadrado
fonte
44
Se não houver outra maneira, como o StackExchange / OpenID funciona?
Hawken
60
O @Hawken StackExchange / OpenID segue o mesmo processo descrito acima. Você é direcionado para um site diferente (SO> SX), confirma sua identidade e, em seguida, volta ao SO com as informações necessárias. O OpenID Spec explica mais, embora a Wikipedia faça isso de maneira mais clara .
Nick Q.
1
Todos os usuários estão logados no cookiemaker.com, na verdade. E ele redireciona o usuário para os diferentes sites com uma mensagem segura e especial que verifica se eles estão conectados e quem são. Como implementar isso é com você, existem infinitas maneiras de fazê-lo. Talvez você possa usar isto: jwt.io
alcuadrado
8
@ Andrew_1510 cookiebakerseria melhor ;-)
Richard Turner
1
Aqui está o post com tag de imagem, essa é uma solução melhor ?
shaijut 13/12/19
70

Tanto quanto eu sei, os cookies são limitados pela política de "mesma origem". No entanto, com o CORS, você pode receber e usar os cookies "Servidor B" para estabelecer uma sessão persistente do "Servidor A" no "Servidor B".

Embora isso exija alguns cabeçalhos no "Servidor B":

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

E você precisará enviar a sinalização " withCredentials " em todas as solicitações do "Servidor A" (ex:xhr.withCredentials = true; )

Você pode ler sobre isso aqui:

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

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

Vitae Aliquam
fonte
11
Isso não funcionará para alguns usuários porque os cookies CORS não funcionarão se os cookies de terceiros estiverem desativados, por exemplo, o Safari por padrão, por exemplo, as configurações do Mozilla . Google mais exemplos e um artigo sobre por que o Facebook não usa cookies de terceiros.
robocat
1
O stack exchange / openID usa CORS?
RayLoveless
1
FWIW eu só testou uma CORS normais withCredentials XHR e funcionou no FF / Safari / Chrome ... embora eu não teria dúvida de que facebook / Google utilizam esquemas mais sofisticados
rogerdpack
30

Não existem cookies entre domínios. Você pode compartilhar um cookie entre foo.example.come bar.example.comnunca entre example.come example2.come por motivos de segurança.

Darin Dimitrov
fonte
1
Oi obrigado pela resposta, você pode adicionar mais clareza na parte de configuração, como criar / configurar domínio e subdomínio no ambiente j2ee ???
SundarJavaDeveloper
1
Essa é uma pergunta mais adaptada ao serverfault.com, na qual você obterá respostas de especialistas no domínio.
Darin Dimitrov
Oi, eu tentei ter dois webapps WebApp.domain.com ==> aqui eu adiciono cookie no respose da seguinte maneira: Cookie cookie = new Cookie ("namedCookie", "test"); cookie.setDomain (". domain.com"); response.addCookie (cookie); WebApp1.domain.com ==> Aqui, tentei acessar o cookie da seguinte forma, mas não consigo acessar o cookie [] cks = request.getCookies (); for (int i = 0; i <cks.length; i ++) {out.print ("cookie encontrado" + cks [i] .getValue ()); } Alguma idéia sobre isso?
SundarJavaDeveloper
2
frequentemente repetida, mas não verdadeira, veja minha resposta abaixo ou aqui stackoverflow.com/questions/16186645/...
Raphael Jeger
4
Como compartilhar cookies entre foo.example.come bar.example.com?
Jeff Tian
24

A solução mais inteligente é seguir o caminho do facebook. Como o facebook sabe quem você é quando visita um domínio? Na verdade, é muito simples :

O botão Curtir permite que o Facebook rastreie todos os visitantes do site externo, independentemente de clicarem ou não. O Facebook pode fazer isso porque eles usam um iframe para exibir o botão. Um iframe é algo como uma janela do navegador incorporada em uma página. A diferença entre usar um iframe e uma imagem simples para o botão é que o iframe contém uma página da Web completa - do Facebook . Não há muita coisa acontecendo nesta página, exceto o botão e as informações sobre quantas pessoas gostaram da página atual.

Então, quando você vê um botão de curtir no cnn.com, na verdade está visitando uma página do Facebook ao mesmo tempo. Isso permite que o Facebook leia um cookie no seu computador, que foi criado na última vez em que você fez login no Facebook.

Uma regra de segurança fundamental em todos os navegadores é que apenas o site que criou um cookie pode lê-lo mais tarde. E essa é a vantagem do iframe: ele permite que o Facebook leia seu cookie do Facebook, mesmo quando você está visitando um site diferente. É assim que eles o reconhecem no cnn.com e exibem seus amigos lá.

Fonte:

Morteza Shahriari Nia
fonte
6
Eu acho que um iframe raramente seria classificado como a melhor ou a maneira mais inteligente de fazer qualquer coisa .. mas é a mais fácil.
Orun
13

Faça o que o Google está fazendo. Crie um arquivo PHP que defina o cookie nos 3 domínios. Em seguida, no domínio em que o tema será definido, crie um arquivo HTML que carregue o arquivo PHP que define o cookie nos outros 2 domínios. Exemplo:

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

Em seguida, adicione um retorno de chamada de onload na tag body. O documento será carregado somente quando as imagens forem carregadas completamente, ou seja, quando os cookies forem definidos nos outros 2 domínios. Onload Callback:

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

setcookie.php

Definimos os cookies nos outros domínios usando um arquivo PHP como este:

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

Agora, os cookies são definidos nos três domínios.

Hossain Khademian
fonte
2
Isso não funciona se o recurso "Bloquear cookies de terceiros" estiver ativado.
Jens
11

Você não pode compartilhar cookies entre domínios. No entanto, você pode permitir que todos os subdomínios tenham acesso. Para permitir que todos os subdomínios example.comtenham acesso, defina o domínio como .example.com.

Porém , não é possível dar otherexample.comacesso aos example.comcookies de.

Daniel Egeberg
fonte
27
como os .google.comcookies aparecem ao navegar no YouTube?
quer
20
Tags de análise do Google. Esses cookies vêm do google.com, não do youtube.com.
Entendu 12/09
8

Você pode tentar enviar o valor do cookie para outro domínio usando uma tag de imagem.

Sua milhagem pode variar ao tentar fazer isso porque alguns navegadores exigem que você tenha uma política P3P adequada no domínio WebApp2 ou o navegador rejeitará o cookie.

Se você consultar a política plus.google.com p3p, verá que a política deles é:

CP = "Esta não é uma política do P3P! Consulte http://www.google.com/support/accounts/bin/answer.py?hl=pt_BR&answer=151657 para obter mais informações."

essa é a política que eles usam para seus botões de +1 para essas solicitações entre domínios.

Outro aviso é que, se você estiver em https, verifique se a tag da imagem está apontando para um endereço https, caso contrário os cookies não serão configurados.

Bryan Focht
fonte
2
Gostaria de elaborar um pouco?
frequente
5

Há uma visão geral decente de como o Facebook faz isso aqui no nfriedly.com

Há também a impressão digital do navegador, que não é a mesma coisa que um cookie, mas serve a um objetivo semelhante, pois ajuda a identificar um usuário com um grau razoável de certeza. Há um post aqui no Stack Overflow que faz referência a um método de impressão digital

byZero
fonte
1

Pode-se usar iframes invisíveis para obter os cookies. Digamos que existem dois domínios, a.com e b.com. Para o index.html do domínio a.com, é possível adicionar (observe a altura = 0 largura = 0):

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

Dessa forma, seu site receberá cookies b.com, pressupondo que http://b.com defina os cookies.

A próxima coisa seria manipular o site dentro do iframe por meio de JavaScript. As operações dentro do iframe podem se tornar um desafio se não for o proprietário do segundo domínio. Porém, no caso de ter acesso aos dois domínios, a página da web correta no src do iframe deve fornecer os cookies que você deseja obter.

Vadym Tyemirov
fonte
5
Apenas um aviso: há alguns problemas sérios com cookies em iframes no Safari. Aparentemente, eles não funcionam em vários domínios.
Mdds #
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

Inclua a origem da interface do usuário e defina Allow Crentials como 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
fonte
1

Criei um módulo NPM, que permite compartilhar dados armazenados localmente entre domínios: https://www.npmjs.com/package/cookie-toss

Usando um iframe hospedado no Domínio A, você pode armazenar todos os seus dados de usuário no Domínio A e referenciá-los postando solicitações no iframe do Domínio A.

Assim, os domínios B, C etc. podem injetar o iframe e enviar solicitações para armazenar e acessar os dados desejados. O domínio A se torna o hub para todos os dados compartilhados.

Com uma lista de permissões de domínio dentro do Domínio A, você pode garantir que apenas seus sites dependentes possam acessar os dados no Domínio A.

O truque é ter o código dentro do iframe no domínio A, capaz de reconhecer quais dados estão sendo solicitados. O README no módulo NPM acima detalha o procedimento.

Espero que isto ajude!

jmealy
fonte
-4

Leia Cookie emWeb 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
fonte
Isso não lidar com a questão OP de utilizar em dois domínios diferentes
Niklas Wulff