Cookie tên miền chéo


246

Tôi có hai ứng dụng web WebApp1 và WebApp2 trong hai miền khác nhau.

  1. Tôi đang đặt cookie trong WebApp1 trong HttpResponse.
  2. Làm cách nào để đọc cùng một cookie từ HttpRequest trong WebApp2?

Tôi biết điều này nghe có vẻ kỳ lạ vì cookie dành riêng cho một tên miền nhất định và chúng tôi không thể truy cập chúng từ các miền khác nhau; Tuy nhiên, tôi đã nghe nói về cookie CROSS-DOMAIN có thể được chia sẻ trên nhiều ứng dụng web. Làm cách nào để thực hiện yêu cầu này bằng cookie CROSS-DOMAIN?

Lưu ý: Tôi đang thử điều này với ứng dụng web J2EE

Câu trả lời:


130

Có, hoàn toàn có thể lấy cookie từ domain1.com bởi domain2.com. Tôi đã có cùng một vấn đề cho một plugin xã hội của mạng xã hội của tôi và sau một ngày nghiên cứu tôi đã tìm thấy giải pháp.

Trước tiên, về phía máy chủ, bạn cần có các tiêu đề sau:

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

Trong tệp PHP bạn có thể sử dụng $_COOKIE[name]

Thứ hai, về phía khách hàng:

Trong yêu cầu ajax của bạn, bạn cần bao gồm 2 tham số

crossDomain: true
xhrFields: { withCredentials: true }

Thí dụ:

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

6
Hoặc nếu bạn không muốn lọc nguồn gốc, chỉ cần sử dụng $ _SERVER ['HTTP_ORIGIN'] thay vì *
Joel Teply

1
Đây là điều duy nhất làm việc cho tôi. Ngoài ra, * không được chấp nhận làm nguồn gốc, vì vậy cần có mẹo của @Joel Teply.
Đoán

4
Điều này sẽ không hoạt động nếu cookie của bên thứ ba bị tắt (tự động đối với một số tình huống trình duyệt). Xem blog.zok.pw/web/2015/10/21/3rd-party-cookies-in-practiceallannienhuis.com/archives/2013/11/03/ trên để biết thêm thông tin.
robocat

4
Đừng sử dụng mẹo của Joel, vì nó "về bản chất" giống như đặt nó thành "*" có thể mở ra các lỗ hổng bảo mật tinh vi nên không được khuyến khích, hãy xem stackoverflow.com/questions/12001269/
Thẻ

5
về phía máy chủ của tên miền nào?
Nick Manning

127

Như những người khác nói, bạn không thể chia sẻ cookie, nhưng bạn có thể làm một cái gì đó như thế này:

  1. tập trung tất cả các cookie trong một tên miền, giả sử cookiemaker.com
  2. Khi người dùng đưa ra yêu cầu đến example.com, bạn chuyển hướng anh ta đến cookiemaker.com
  3. cookiemaker.com chuyển hướng anh ta trở lại example.com với thông tin bạn cần

Tất nhiên, nó không hoàn toàn an toàn và bạn phải tạo một số loại giao thức nội bộ giữa các ứng dụng của mình để thực hiện điều đó.

Cuối cùng, sẽ rất khó chịu cho người dùng nếu bạn làm điều gì đó tương tự trong mọi yêu cầu, nhưng không phải nếu đó chỉ là lần đầu tiên.

Nhưng tôi nghĩ không còn cách nào khác ...


44
Nếu không có cách nào khác, thì StackExchange / OpenID hoạt động như thế nào?
Hawken

60
@Hawken StackExchange / OpenID tuân theo quy trình tương tự như được mô tả ở trên. Bạn được chuyển đến một trang web khác (SO> SX), xác nhận danh tính của bạn và sau đó được chuyển trở lại SO với thông tin bạn cần. OpenID Spec giải thích nhiều hơn, mặc dù Wikipedia làm điều đó rõ ràng hơn .
Nick Q.

1
Tất cả người dùng đã đăng nhập vào cookiemaker.com thực sự. Và nó chuyển hướng người dùng đến các trang web khác nhau bằng một thông điệp đặc biệt và an toàn để xác minh rằng họ đã đăng nhập và họ là ai. Làm thế nào để thực hiện nó là tùy thuộc vào bạn, có vô số cách để làm như vậy. Có lẽ bạn có thể sử dụng cái này: jwt.io
alcuadrado 10/07/2015

8
@ Andrew_1510 cookiebakersẽ tốt hơn ;-)
Richard Turner

1
Đây là bài viết với thẻ hình ảnh, đó có phải là một giải pháp tốt hơn ?
shaijut

70

Theo tôi biết, cookie bị giới hạn bởi chính sách "cùng nguồn gốc". Tuy nhiên, với CORS, bạn có thể nhận và sử dụng cookie "Máy chủ B" để thiết lập phiên liên tục từ "Máy chủ A" trên "Máy chủ B".

Mặc dù, điều này đòi hỏi một số tiêu đề trên "Máy chủ B":

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

Và bạn sẽ cần gửi cờ " withCredentials " trên tất cả các yêu cầu "Máy chủ A" (ví dụ xhr.withCredentials = true;:)

Bạn có thể đọc nó ở đây:

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

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


11
Điều này sẽ không hoạt động đối với một số người dùng vì cookie CORS sẽ không hoạt động nếu cookie của bên thứ ba bị tắt, ví dụ như Safari theo mặc định, ví dụ như cài đặt Mozilla . Google thêm ví dụ và một bài viết về lý do tại sao Facebook không sử dụng cookie của bên thứ ba.
robocat

1
Có ngăn xếp trao đổi / openID sử dụng CORS?
RayLovless

1
FWIW Tôi vừa thử nghiệm một CORS bình thường với XHRentials XHR và nó đã hoạt động trên FF / Safari / Chrome ... mặc dù tôi không nghi ngờ rằng facebook / google sử dụng các sơ đồ phức tạp hơn
rogerdpack

29

Không có thứ gọi là cookie tên miền chéo. Bạn có thể chia sẻ một cookie giữa foo.example.combar.example.comnhưng không bao giờ giữa example.comexample2.comvà cho lý do an ninh.


1
Xin chào cảm ơn bạn đã trả lời, bạn có thể vui lòng thêm rõ ràng hơn về phần cấu hình, làm thế nào để tạo / cấu hình tên miền và tên miền phụ trong môi trường j2ee ???
SundarJava Nhà phát triển

1
Đây là một câu hỏi phù hợp hơn với serverfault.com nơi bạn sẽ nhận được câu trả lời từ các chuyên gia trong miền.
Darin Dimitrov

Xin chào, tôi đã thử có hai ứng dụng web WebApp.domain.com ==> ở đây tôi thêm cookie theo quy định như sau: Cookie cookie = new Cookie ("tênCookie", "test"); cookie.setDomain (". domain.com"); đáp ứng.addCookie (cookie); WebApp1.domain.com ==> Ở đây tôi đã cố gắng truy cập cookie như sau, nhưng không thể truy cập Cookie [] cks = request.getCookies (); for (int i = 0; i <cks.length; i ++) {out.print ("tìm thấy cookie" + cks [i] .getValue ()); } Có ý tưởng nào về điều này?
SundarJava Nhà phát triển

2
thường lặp đi lặp lại nhưng không đúng sự thật, xem câu trả lời của tôi bên dưới hoặc ở đây stackoverflow.com/questions/16186645/NH
Raphael Jeger

4
Làm thế nào để chia sẻ cookie giữa foo.example.combar.example.com?
Jeff Tian

24

Giải pháp thông minh nhất là đi theo con đường của facebook về điều này. Làm thế nào để facebook biết bạn là ai khi bạn truy cập bất kỳ tên miền nào? Nó thực sự rất đơn giản :

Nút Like thực sự cho phép Facebook theo dõi tất cả khách truy cập của trang bên ngoài, bất kể họ có nhấp vào đó hay không. Facebook có thể làm điều đó vì họ sử dụng iframe để hiển thị nút. Một iframe giống như một cửa sổ trình duyệt được nhúng trong một trang. Sự khác biệt giữa việc sử dụng iframe và hình ảnh đơn giản cho nút là iframe chứa một trang web hoàn chỉnh - từ Facebook . Không có nhiều diễn ra trên trang này, ngoại trừ nút và thông tin về số lượng người đã thích trang hiện tại.

Vì vậy, khi bạn thấy một nút thích trên cnn.com, bạn thực sự đang truy cập một trang Facebook cùng một lúc. Điều đó cho phép Facebook đọc cookie trên máy tính của bạn, cái mà nó đã tạo ra lần cuối cùng bạn đăng nhập vào Facebook.

Một quy tắc bảo mật cơ bản trong mọi trình duyệt là chỉ có trang web đã tạo cookie mới có thể đọc nó sau này. Và đó là lợi thế của iframe: nó cho phép Facebook đọc cookie Facebook của bạn ngay cả khi bạn đang truy cập một trang web khác. Đó là cách họ nhận ra bạn trên cnn.com và hiển thị bạn bè của bạn ở đó.

Nguồn:


6
Tôi nghĩ rằng iframe sẽ hiếm khi được phân loại là cách tốt nhất hoặc thông minh nhất để làm bất cứ điều gì .. nhưng nó là cách dễ nhất.
Orun

13

Làm những gì Google đang làm. Tạo một tệp PHP đặt cookie trên cả 3 miền. Sau đó, trên miền mà chủ đề sẽ được đặt, hãy tạo một tệp HTML sẽ tải tệp PHP đặt cookie trên 2 tên miền khác. Thí dụ:

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

Sau đó thêm một cuộc gọi lại onload trên thẻ cơ thể. Tài liệu sẽ chỉ tải khi hình ảnh tải hoàn toàn, đó là khi cookie được đặt trên 2 tên miền khác. Gọi lại tải:

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

setcookie.php

Chúng tôi đặt cookie trên các miền khác bằng tệp PHP như thế này:

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

Bây giờ cookie được đặt trên ba miền.


2
Điều này không hoạt động nếu tính năng 'Chặn cookie của bên thứ ba được bật.
Jens

11

Bạn không thể chia sẻ cookie trên các tên miền. Tuy nhiên, bạn có thể cho phép tất cả các tên miền phụ có quyền truy cập. Để cho phép tất cả các tên miền phụ example.comcó quyền truy cập, hãy đặt tên miền thành.example.com .

Mặc dù không thể cấp otherexample.comquyền truy cập vào example.comcookie.


27
Làm thế nào mà .google.comcookie xuất hiện khi duyệt YouTube?
Hawken

20
Thẻ phân tích của Google. Những cookie đó đến từ google.com, không phải từ youtube.com.
Entendu

8

Bạn có thể cố gắng đẩy val cookie sang tên miền khác bằng thẻ hình ảnh.

Số dặm của bạn có thể thay đổi khi cố gắng thực hiện việc này vì một số trình duyệt yêu cầu bạn phải có Chính sách P3P phù hợp trên miền WebApp2 hoặc trình duyệt sẽ từ chối cookie.

Nếu bạn nhìn vào chính sách plus.google.com p3p, bạn sẽ thấy chính sách của họ là:

CP = "Đây không phải là một chính sách P3P! Xem http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 để biết thêm."

đó là chính sách họ sử dụng cho các nút +1 của mình cho các yêu cầu tên miền chéo này.

Một cảnh báo khác là nếu bạn ở trên https, hãy đảm bảo rằng thẻ hình ảnh cũng đang trỏ đến một địa chỉ https nếu không các cookie sẽ không được đặt.


2
Muốn trau chuốt một chút?
thường xuyên


1

Người ta có thể sử dụng iframe vô hình để lấy cookie. Giả sử có hai tên miền, a.com và b.com. Đối với index.html của tên miền a.com, người ta có thể thêm (chú ý height = 0 width = 0):

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

Bằng cách đó, trang web của bạn sẽ nhận được cookie b.com giả định rằng http://b.com đặt cookie.

Điều tiếp theo sẽ là thao túng trang web bên trong iframe thông qua JavaScript. Các hoạt động bên trong iframe có thể trở thành một thách thức nếu một người không sở hữu miền thứ hai. Nhưng trong trường hợp có quyền truy cập vào cả hai miền giới thiệu đúng trang web tại src của iframe thì nên cung cấp các cookie mà người ta muốn nhận.


5
Chỉ là một cảnh báo: Có một số vấn đề nghiêm trọng với cookie trong iframe trên Safari. Họ dường như không làm việc xuyên miền.
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

Bao gồm nguồn gốc UI và đặt Cho phép các giá trị thành đúng

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

1

Tôi đã tạo một mô-đun NPM, cho phép bạn chia sẻ dữ liệu được lưu trữ cục bộ trên các miền: https://www.npmjs.com/package/cookie-toss

Bằng cách sử dụng iframe được lưu trữ trên Miền A, bạn có thể lưu trữ tất cả dữ liệu người dùng của mình trên Miền A và tham chiếu dữ liệu đó bằng cách đăng các yêu cầu lên iframe của Miền A.

Do đó, Tên miền B, C, v.v. có thể tiêm iframe và gửi yêu cầu tới nó để lưu trữ và truy cập dữ liệu mong muốn. Tên miền A trở thành trung tâm cho tất cả dữ liệu được chia sẻ.

Với danh sách trắng tên miền bên trong Miền A, bạn có thể đảm bảo chỉ các trang web phụ thuộc của bạn mới có thể truy cập dữ liệu trên Miền A.

Mẹo nhỏ là để mã bên trong iframe trên Miền A có thể nhận ra dữ liệu nào đang được yêu cầu. README trong mô-đun NPM ở trên đi sâu hơn vào quy trình.

Hi vọng điêu nay co ich!


-4

Đọc Cookie trongWeb 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;
                            }
                        }
                    }

Điều này không xử lý câu hỏi OP sử dụng trên hai miền khác nhau
Niklas Wulff
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.