我注意到浏览器在Cookie方面存在一些真正的不一致。
这将是相当长的,所以忍受我。
注意:我在我的主机文件中设置了一个名为" testdomain.com"的域名,这个 bug WONT在使用&时工作#34;本地主机"
注意2:我很想知道如果按照名称检索cookie,如果它提供了一系列cookie,那么它在Apache / PHP上是如何工作的。
维基百科指出:http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path
域名与路径
cookie域和路径定义了范围 cookie - 他们告诉浏览器只应将cookie发送回去 给定域和路径的服务器。 如果没有指定,他们 默认为所请求对象的域和路径。
所以如果我们推倒:
Response.Cookies.Add(new HttpCookie("Banana", "2")
{
});
我们应该获得一个cookie,其中使用的域是来自请求对象的域,在这种情况下,它应该是" testdomain.com"。
W3在cookie规范中说明:http://www.w3.org/Protocols/rfc2109/rfc2109
域=域
可选。 Domain属性指定用于的域 cookie有效。 必须始终启动明确指定的域 带点。
所以如果我们推倒:
Response.Cookies.Add(new HttpCookie("Banana", "1")
{
Domain = Request.Url.Host
});
我们明确地推下了主机名,我们应该在cookie上设置一个以点为前缀的域名,在这种情况下它应该是" .testdomain.com"。
它还说明了维基百科上的内容:
域默认为请求主机。 (注意,没有点 请求主机的开头。)
到目前为止我?
如果我使用第一种方法,则定义一个域:
Response.Cookies.Add(new HttpCookie("Banana", "1")
{
Domain = Request.Url.Host
});
结果如下:
IE9:1个cookie
Opera:1个cookie
Firefox:1个Cookie
Chrome:1个Cookie
如您所见,Opera和IE都设置了一个没有点前缀的EXPLICIT域。
Firefox和Chrome DO都使用点前缀设置EXPLICIT域。
如果我使用以下代码:
Response.Cookies.Add(new HttpCookie("Banana", "2")
{
});
IE / Opera:两者都有完全相同的结果,没有点前缀的域。
有趣的是,Firefox和Chrome都创建了没有点前缀的cookie。
(我清除了所有cookie并再次运行代码)
火狐:
Chrome:
这是有趣的地方。如果我像这样一个接一个地写饼干:
Response.Cookies.Add(new HttpCookie("Banana", "1")
{
Domain = Request.Url.Host
});
Response.Cookies.Add(new HttpCookie("Banana", "2")
{
});
个人我希望浏览器中存在一个cookie,因为我认为它基于cookie名称。
这是我观察到的:
在IE / Opera中,LAST cookie集是使用的cookie。这是因为Cookie名称和域名相同。
如果您使用点明确定义域名,则两个浏览器仍会看到1个cookie,即同名的最后一个cookie。
另一方面,Chrome和Firefox会看到超过1个Cookie:我编写了以下JavaScript来将值转储到页面:
<script type="text/javascript">
(function () {
var cookies = document.cookie.split(';');
var output = "";
for (var i = 0; i < cookies.length; i++) {
output += "<li>Name " + cookies[i].split('=')[0];
output += " - Value " + cookies[i].split('=')[1] + "</li>";
}
document.write("<ul>" + output + "</ul>");
})();
</script>
结果如下:
IE - 2个cookie设置(浏览器看到1):
Opera - 设置了2个cookie(浏览器看到1):
Firefox - 2个Cookie集和浏览器看到2!:
Chrome - 2个Cookie设置,浏览器看到2个!:
现在你可能想知道wtf这一切。
嗯:
问题......
我们必须更改身份验证,以便在我们将其推送时在Cookie中指定域。
这打破了Chrome和Firefox,用户无法再登录,因为服务器会尝试验证旧的身份验证Cookie。这是因为(根据我的理解)它使用身份验证Cookie名称来检索cookie。
即使有两个cookie,第一个检索到的是旧的,验证失败,用户没有登录。有些正确的cookie首先在列表中,验证成功。 ..
最初,我们通过推送旧域的cookie来解决这个问题。这适用于Chrome和Firefox。
但它现在破坏了IE / Opera,因为两个浏览器都不关心域名,只根据名称比较cookie。
我的结论是,cookie上的域名完全是浪费时间。
假设我们必须指定域,并且我们不能依赖用户清除其浏览器缓存。我们如何解决这个问题?
深入了解.NET如何签署用户。
if (FormsAuthentication._CookieDomain != null)
{
httpCookie.Domain = FormsAuthentication._CookieDomain;
}
表单身份验证完全有可能推送过期的Auth cookie,这与用户通过身份验证的cookie完全无关。它不使用当前的Auth Cookie域。
无论如何它都无法使用,因为域名不会被cookie推回到服务器。
看起来FormsAuthentication真的坏了。如果在对用户进行身份验证时在cookie上使用显式域名,请等待会话超时,然后刷新页面,生成FormsAuthentication使用的cookie的方法导致域为null,这会导致浏览器分配无网域。
它需要预先为表单分配一个域,以便将其分配给cookie,这会破坏多租户系统......
答案 0 :(得分:9)
@WilliamBZA的建议帮助解决了最初的问题,但随后导致cookie创建隐式域cookie的注销/会话超时错误让我得出结论解决方案是...
不要在.NET中使用明确的Cookie ...永远
有太多问题,确定可以通过明确表单/域,Cookie /域等来解决。确保在任何地方都使用正确的域。但是,如果您的应用程序托管多个域或多租户,那么它就会变得太成问题。
吸取教训。不要使用明确的cookie。
答案 1 :(得分:5)
无法帮助为什么对Cookie的处理方式不同,但快速解决方法是为每个子应用程序使用不同的Cookie名称,而不是使用Cookie的域名。
如果是Forms Authentication,请更改ASPXAUTH cookie的名称。