跨域饼干

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

  1. 我在WebApp1的HttpResponse中设置了一个cookie。
  2. 如何从WebApp2中的HttpRequest读取相同的cookie ?

我知道这听起来很奇怪,因为cookie是特定于给定域的,我们不能从不同的域访问它们;不过我听说过跨域cookie,它可以在多个web应用程序之间共享。如何使用跨域cookie实现这一需求?

注意:我正在尝试使用J2EE web应用程序

519530 次浏览

没有所谓的跨域cookie。你可以在foo.example.combar.example.com之间共享cookie,但不能在example.comexample2.com之间共享,这是出于安全原因。

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

不过,让other.example访问example.com的cookie是不可能的。

就像其他人说的,你不能分享cookie,但你可以这样做:

  1. 将所有cookie集中在一个域中,例如cookiemaker.example
  2. 当用户请求example.com时,你将他重定向到cookiemaker.example
  3. cookiemaker.example将他重定向回带有你需要的信息的example.com

当然,它不是完全安全的,你必须在你的应用程序之间创建某种内部协议来做到这一点。

最后,如果在每个请求中都这样做,对用户来说会非常讨厌,但如果只是第一个请求就不会。

但我认为没有别的办法了。

Facebook在nfriedly.com上是怎么做的有一个不错的概述

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

据我所知,饼干受到“同源”的限制。政策。然而,有了CORS,你可以接收和使用“服务器”;cookie从“服务器a”建立持久会话;在“服务器”上。

虽然,这需要一些头quot;服务器quot;

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

你需要发送旗帜"withCredentials"在所有“服务器”上;请求(例如:xhr.withCredentials = true;)

你可以在这里阅读:

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

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

你可以使用隐形的iframe来获取cookie。假设有两个域,a.exampleb.example。对于域a.exampleindex.html,可以添加(注意height=0 width=0):

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

这样,你的网站将获得b.example cookie,假设http://b.example设置了cookie。

下一件事是通过JavaScript在iframe中操作站点。如果不拥有第二个域,iframe内部的操作可能会成为一个挑战。但是,如果能够访问这两个域,在iframe的src中引用正确的网页应该会给出一个想要获得的cookie。

您可以尝试使用图像标记将cookie val推到另一个域。

当尝试这样做时,您的里程可能会有所不同,因为一些浏览器要求您在WebApp2域中有一个正确的P3P策略,否则浏览器将拒绝cookie。

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

CP="这不是P3P策略!更多信息请参见http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657。”

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

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

是的,通过domain2.exampledomain1.example获得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
}

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

<html>
<head></head>
<body>
<p>Please wait.....</p>
<img src="http://domain2.example/setcookie.php?theme=whateveryourthemehere" />
<img src="http://domain3.example/setcookie.php?theme=whateveryourthemehere" />
</body>
</html>

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

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


setcookie.php

我们使用PHP文件在其他域上设置cookie,如下所示:

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

现在在三个域中设置了cookie。

Web Api中读取Cookie

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;
}
}
}
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");
}
});
}
}

. config

包括UI原点和设置允许凭据为真

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

最聪明的解决办法就是效仿facebook的做法。当你访问任何域名时,facebook如何知道你是谁?它实际上非常简单的:

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

所以当你在cnn.com上看到一个“喜欢”按钮时,你实际上是在同时访问一个Facebook页面。这使得Facebook可以读取你电脑上的cookie,这些cookie是它在你上次登录Facebook时创建的。

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

来源:

我已经创建了一个NPM模块,它允许你跨域共享本地存储的数据: https://www.npmjs.com/package/cookie-toss < / p >

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

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

使用域a中的域白名单,您可以确保只有您依赖的站点可以访问域a上的数据。

诀窍是在域A上的iframe中有能够识别正在请求的数据的代码。上面NPM模块中的README更深入地介绍了这个过程。

希望这能有所帮助!

跨域cookie 不被允许(即站点A不能在站点B上设置cookie)。

但是一旦站点a设置了cookie,你甚至可以在请求从站点B到站点A (即跨域请求)中发送cookie:

在发出请求之前,从不同的域不能为自己的域设置cookie值,除非withCredentials设置为true XMLHttpRequest。通过将withCredentials设置为true 仍然会遵守同源政策吗不能获得的第三方cookie可以由请求脚本通过document.cookie或从响应头访问。

一定要做到以下几点:

  1. 在响应中设置cookie时
    • 如果请求是跨站点的,Set-Cookie 响应头包含SameSite=None(注意从www.example.devstatic.example.dev的请求实际上是一个同一地点请求,并且可以使用SameSite=Strict)
    • 如果通过HTTPS服务,Set-Cookie 响应头应该包括Secure属性;如在这里在这里所示
  2. 发送/接收cookie时:
    • 请求是用withCredentials: true发出的,正如在其他答案在这里在这里中提到的,,包括原始请求,其响应是cookie首先设置的
      • 对于获取API,这个属性是credentials: 'include', vs withCredentials: true
      • 对于jQuery的ajax方法,注意你可能需要提供参数crossDomain: true
    • 服务器响应包括跨源头,如Access-Control-Allow-OriginAccess-Control-Allow-CredentialsAccess-Control-Allow-HeadersAccess-Control-Allow-Methods
      • 正如@nabrown指出的:"注意"Access-Control-Allow-Origin"不能是通配符(*)值,如果使用withCredentials: true"(参见@nabrown的评论,其中解释了一种解决方法。
  3. <李>一般:
    • 您的浏览器尚未禁用第三方cookie。(*见下文)

< em >不需要< / em >的东西(只使用上面的):

  1. Set-Cookie中的domain属性;你可以选择一个根域(例如,a.example.com可以将一个cookie的域值设置为example.com,但这不是必要的;cookie仍然会被发送到a.example.com,即使是从b.other-site.example发送
  2. 为了cookie在Chrome开发工具中可见,“应用程序”;选项卡;如果cookie HttpOnly属性的值是真正的, Chrome 不会在应用程序选项卡中显示cookie值(它应该在初始请求中显示cookie值,在后续响应中显示发送,其中withCredentials: true)

注意"path"和“;site"为了Cookie的目的。“path"是安全相关的;“site"与安全相关的:

路径

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

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

网站

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

准确理解“site”在这里的意思是很有帮助的。该站点是域后缀和它前面的域部分的组合。例如,www.example.dev域是example.dev站点的一部分…

这意味着从www.example.devstatic.example.dev的请求是一个sameSite请求(url的唯一区别是在子域)。

公共后缀列表定义了这个,所以 它不只是像。com这样的顶级域名,还包括服务 像github.io < / p >

这意味着从my-project.github.ioyour-project.github.io的请求是一个跨站点请求(这些url位于不同的域,因为github.io是域后缀;域your-projectmy-project是不同的;因此不同的网站)

这意味着公共后缀的在左边是什么;是子域(但是子域是主机的部分;见奖金回复在这个答案)

  • wwwwww.example.dev中的子域;与static.example.dev相同的站点
  • your-projectyour-project.github.io中的域;将站点分离为my-project.github.io

在这个URL https://www.example.com:8888/examples/index.html中,记住这些部分:

  • the "协议": https://
    • the“scheme”:https
  • 端口:8888
  • “域名”;又名location.hostname: www.example.com
    • “域名后缀”;即“顶级域名”;(TLD): com
    • 域名:example
    • 子域:www(子域可以是单层(如www)或多层(比如__ABC3中的foo.bar)
  • <李>“site"(如在&;cross-site"如果另一个URL有不同的“站点”;值):example.com
    • “site"=“;domain"+ "域名后缀;= example.com
  • the " path": /examples/index.html

有用的链接:

(小心;我在Chrome隐身标签测试我的功能;根据我chrome://settings/cookies;我的设置是“屏蔽Incognito中的第三方cookie”,所以我不能在Incognito中测试跨站cookie。)

浏览器打开URL chrome://settings/cookies,显示&;Block第三方cookies in Incognito

因为很难做第三方cookie,也有些浏览器不允许这样做。

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

除了@Ludovic(已批准的答案)的答案外,我们需要在获得set-cookies报头时检查另一个选项,

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

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

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

或者在不确定上下文路径时使用下面的值

Path=/;

基于浏览器的存储主要有三种:

  1. 会话存储
  2. 本地存储
  3. cookie存储

  • 安全的饼干 -被加密的网站用来提供保护,免受黑客的任何可能的威胁。

  • 访问饼干 - document.cookie。这意味着这个cookie是公开的,可以通过跨站点脚本来利用。保存的cookie值可以通过浏览器控制台看到。

作为预防措施,您应该总是尝试使用JavaScript使您的cookie在客户端不可访问。

  • HTTPonly -确保cookie不能使用JavaScript代码访问。这是防止交叉脚本攻击的最重要的保护形式。

  • 安全属性 -确保浏览器将拒绝cookie,除非连接发生在HTTPS上。

  • sameSite属性提高cookie安全性,避免隐私泄露。

  • sameSite =松懈 -它被设置为Lax (sameSite = Lax),这意味着只有当浏览器URL中的域与cookie的域匹配时才设置cookie,从而消除了第三方的域。这将限制跨站点共享,即使是在同一发布者拥有的不同域名之间。我们需要包含SameSite=None来避免Lax的新默认值:

注意:有一个规范草案要求当SameSite属性被设置为“none”时Secure属性被设置为true。一些web浏览器或其他客户端可能采用此规范。

  • 使用include作为{ withCredentials: true }必须包含来自前端的请求的所有cookie。
const data = { email: 'youremailaddress@gmail.com' , password: '1234' };
const response = await axios.post('www.yourapi.com/login', data , { withCredentials: true });
  • Cookie只能在安全的HTTPS连接上被接受。为了使其工作,我们必须将web应用程序移动到HTTPS。

在express.js

res.cookie('token', token, {
maxAge: 1000 * 60 * 60 * 24, // would expire after (for 15 minutes  1000 * 60 * 15 ) 15 minutes
httpOnly: true, // The cookie only accessible by the web server
sameSite: 'none',
secure: true, // Marks the cookie to be used with HTTPS only.
});

参考1, 参考2