跨域Cookie

时间:2010-07-27 09:10:53

标签: cookies web-applications cross-domain

我在两个不同的域中有两个webapps WebApp1和WebApp2。

  1. 我在HttpResponse中的WebApp1中设置了一个cookie。
  2. 如何在WebApp2中从HttpRequest读取相同的cookie?
  3. 我知道这听起来很奇怪,因为Cookie特定于某个域,我们无法从不同的域访问它们;我听说过CROSS-DOMAIN cookie可以在多个webapps之间共享。如何使用CROSS-DOMAIN cookie实现此要求?

    注意:我正在尝试使用J2EE webapps

16 个答案:

答案 0 :(得分:114)

正如其他人所说,你不能共享cookie,但你可以这样做:

  1. 将所有Cookie集中在一个域中,比如说cookiemaker.com
  2. 当用户向example.com发出请求时,您将其重定向到cookiemaker.com
  3. cookiemaker.com使用您需要的信息将他重定向回example.com
  4. 当然,它并不完全安全,你必须在你的应用程序之间创建某种内部协议才能做到这一点。

    最后,如果您在每个请求中执行类似的操作,对用户来说会非常烦人,但如果只是第一个请求则不会。

    但我认为没有别的办法......

答案 1 :(得分:101)

是的,绝对有可能通过domain2.com从domain1.com获取cookie。我对社交网络的社交插件也有同样的问题,经过一天的研究后我找到了解决方案。

首先,在服务器端,您需要具有以下标头:

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

在PHP文件中,您可以使用$_COOKIE[name]

其次,在客户端:

在您的ajax请求中,您需要包含2个参数

crossDomain: true
xhrFields: { withCredentials: true }

示例:

type: "get",
url: link,
crossDomain: true,
dataType: 'json',
xhrFields: {
  withCredentials: true
}

答案 2 :(得分:59)

据我所知,cookies受到“同源”政策的限制。但是,使用CORS,您可以接收并使用“Server B”cookie从“Server B”上的“Server A”建立持久会话。

虽然,这需要“服务器B”上的一些标题:

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

您需要在所有“服务器A”请求中发送标记“ withCredentials ”(例如:xhr.withCredentials = true;

你可以在这里阅读:

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

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

答案 3 :(得分:21)

没有跨域cookie这样的东西。您可以在foo.example.combar.example.com之间共享Cookie,但绝不会在example.comexample2.com之间共享,这是出于安全原因。

答案 4 :(得分:10)

做谷歌正在做的事情。创建一个PHP文件,在所有3个域上设置cookie。然后在主题要设置的域上,创建一个HTML文件,该文件将加载在其他2个域上设置cookie的PHP文件。例如:

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

然后在body标签上添加onload回调。只有当图像完全加载时才会加载文档,即在其他2个域上设置cookie时。 Onload回调:

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

setcookie.php

我们使用这样的PHP文件在其他域上设置cookie:

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

现在,Cookie已在三个域上设置。

答案 5 :(得分:8)

您无法跨域共享Cookie。但是,您可以允许所有子域都具有访问权限。要允许example.com的所有子域都具有访问权限,请将域设置为.example.com

虽然不可能otherexample.com访问example.com的Cookie。

答案 6 :(得分:7)

您可以尝试使用图片标记将Cookie val推送到另一个域。

尝试执行此操作时,您的里程可能会有所不同,因为某些浏览器要求您在WebApp2域上拥有正确的P3P Policy,否则浏览器将拒绝该Cookie。

如果您查看plus.google.com p3p政策,您会看到他们的政策是:

CP =“这不是P3P政策!有关详细信息,请参阅http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657。”

这是他们用于这些跨域请求的+1按钮的策略。

另一个警告是,如果您使用https,请确保图像标记指向https地址,否则不会设置Cookie。

答案 7 :(得分:5)

how Facebook does it here on nfriedly.com

有一个不错的概述

还有浏览器指纹识别,它与cookie不同,但它的用途相似,因为它可以帮助您识别具有相当程度的确定性的用户。有一篇帖子here on Stack Overflow引用了一种指纹识别方法

答案 8 :(得分:3)

跨站点Cookie 被允许,如果:

  1. Set-Cookie响应标头包括herehere中的SameSite=None; Secure
  2. 并且您的浏览器尚未禁用第三方Cookie。*

让我们澄清一个“域”与一个“站点”;我总能很快想起“ URL的解剖”对我有帮助。在此网址https://example.com:8888/examples/index.html中,请记住以下主要部分(从this paper中获取):

  • “协议”:https://
  • “主机名/主机”:example.com
  • “端口”:8888

“路径”部分为:/examples/index.html。注意“路径”和“站点”之间的区别。

路径

服务器可以在Path中设置Set-Cookie属性,但似乎与安全性无关:

请注意,path是为了提高性能,而不是出于安全性。即使路径不匹配,具有相同来源的网页仍可以通过document.cookie访问cookie。

站点

根据web.dev article,SameSite属性可以限制或允许跨站点cookie;但是什么是“站点”?

准确了解“站点”在这里的含义是有帮助的。该站点是域后缀与域后缀的一部分的组合。例如,www.web.dev域是web.dev网站的一部分。

这意味着web.dev左侧 是一个子域;是的,www是子域(但subdomain is a part of the host

在此URL https://www.example.com:8888/examples/index.html中,请记住以下部分:

  • “协议”:https://
  • “主机名”又称“主机”:example.com
  • (在“ en.wikipedia.org”这样的情况下,整个“ en.example.com”也是一个主机名)
  • “端口”:8888
  • “站点”:www.example.com
  • “域”:example.com
  • “子域”:www

有用的链接:

注意;我正在Chrome隐身标签中测试我的功能;根据我的chrome://settings/cookies;我的设置是“阻止隐身第三方Cookie”,因此我无法在隐身模式下测试跨网站Cookie。

a browser is open to the URL chrome://settings/cookies, which shows that "Block third-party cookies in Incognito" setting is set, choose a setting in your browser that will allow third-party cookies

答案 9 :(得分: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

包含UI来源并将Allow Crentials设置为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>

答案 10 :(得分:1)

最聪明的解决方案是遵循Facebook的道路。当你访问任何域名时,facebook如何知道你是谁?它实际上非常simple

“赞”按钮实际上允许Facebook跟踪外部网站的所有访问者,无论他们是否点击它们。 Facebook可以这样做,因为他们使用 iframe 来显示按钮。 iframe类似于页面中的嵌入式浏览器窗口。使用iframe和按钮的简单图像之间的区别在于 iframe包含完整的网页 - 来自Facebook 。除了按钮和有多少人喜欢当前页面的信息外,此页面上没有太多内容。

因此,当您在cnn.com上看到类似按钮时,您实际上是在同时访问Facebook页面。这允许Facebook在您的计算机上读取cookie,这是您上次登录Facebook时创建的。

每个浏览器中的基本安全规则是,只有创建cookie的网站才能在以后阅读。这就是iframe的优势:它允许Facebook即使在您访问其他网站时也能阅读您的Facebook-cookie。这就是他们如何在cnn.com上认出你并在那里展示你的朋友。

来源:

答案 11 :(得分:1)

我创建了一个NPM模块,该模块允许您跨域共享本地存储的数据: https://www.npmjs.com/package/cookie-toss

通过使用托管在域A上的iframe,您可以将所有用户数据存储在域A上,并通过将请求发布到域A iframe来引用这些数据。

因此,域B,C等可以注入iframe并向其发布请求以存储和访问所需数据。域A成为所有共享数据的中心。

使用域A内的域白名单,可以确保只有从属站点可以访问域A上的数据。

诀窍是将代码放在域A的iframe中,该代码能够识别正在请求的数据。上面的NPM模块中的README对该过程进行了更深入的介绍。

希望这会有所帮助!

答案 12 :(得分:0)

可以使用隐形iframe来获取Cookie。假设有两个域名,a.com和b.com。对于域a.com的index.html,可以添加(通知高度= 0宽度= 0):

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

这样,假设http://b.com设置了Cookie,您的网站就会获得b.com Cookie。

接下来就是通过JavaScript操纵iframe中的网站。如果没有第二个域,iframe中的操作可能会成为一个挑战。但是,如果有权访问这两个域,请参考iframe的src中的正确网页,以便给出想要获得的cookie。

答案 13 :(得分:0)

由于很难制作第三方Cookie,而且某些浏览器也不允许这样做。

您可以尝试将它们存储在HTML5本地存储中,然后将其与前端应用程序的每个请求一起发送。

答案 14 :(得分:0)

除了@Ludovic(approved answer) 答案外,我们还需要在获取 set-cookies 标头时再检查一个选项,

set-cookie: SESSIONID=60B2E91C53B976B444144063; Path=/dev/api/abc; HttpOnly

还要检查 Path 属性值。这应该与您的 API 起始上下文路径相同,如下所示

https://www.example.com/dev/api/abc/v1/users/123

或在不确定上下文路径时使用以下值

Path=/;

答案 15 :(得分:-3)

Cookie

中阅读Web 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;
                            }
                        }
                    }