我注意到浏览器之间在 cookie 方面存在一些真正的不一致。
这将是相当长的,所以请耐心等待。
注意:我在我的主机文件中设置了一个名为“testdomain.com”的域,这个错误在使用“localhost”时不会起作用。
注意2:我很想知道这在 Apache/PHP 上是如何工作的,如果您按名称检索 cookie,如果它返回一组 cookie。
维基百科
维基百科指出:http ://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path
域和路径
cookie 域和路径定义了 cookie 的范围——它们告诉浏览器 cookie 应该只针对给定的域和路径发送回服务器。如果未指定,则默认为所请求对象的域和路径。
因此,如果我们向下推:
Response.Cookies.Add(new HttpCookie("Banana", "2")
{
});
我们应该得到一个 cookie,使用的域是来自请求对象的域,在这种情况下它应该是“testdomain.com”。
W3
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”。
它还说明了维基百科上的内容:
域默认为请求主机。(请注意,request-host 的开头没有点。)
跟我到现在?
如果我使用第一种方法,定义一个域:
Response.Cookies.Add(new HttpCookie("Banana", "1")
{
Domain = Request.Url.Host
});
这是结果:
IE9:1个cookie
歌剧:1个饼干
火狐:1个cookie
铬:1个饼干
如您所见,Opera 和 IE 都设置了一个没有点前缀的 EXPLICIT 域。
Firefox 和 Chrome 都使用点前缀设置 EXPLICIT 域。
如果我使用以下代码:
Response.Cookies.Add(new HttpCookie("Banana", "2")
{
});
IE / Opera:两者的结果完全相同,没有点前缀的域。
有趣的是,Firefox 和 Chrome 都创建没有点前缀的 cookie。
(我清除了所有 cookie 并再次运行代码)
火狐:
铬合金:
有趣的位
这就是有趣的地方。如果我像这样一个接一个地写饼干:
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 会看到多个 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!:
现在你可能想知道这一切都是什么。
好:
- 当您在 C# 中按名称访问 cookie 时,它会为您提供 1 个 cookie。(第一个具有该名称的 cookie)
- 浏览器将所有 cookie 发送到服务器
- 除了 cookie 的键/值之外,浏览器不会发送任何信息。(这意味着服务器不关心域)
- 如果您通过索引检索它们,您可以访问同名的两个 cookie
问题...
当我们按下它时,我们必须更改我们的身份验证以在 cookie 中指定域。
这破坏了 Chrome 和 Firefox,用户不再能够登录,因为服务器会尝试验证旧的 auth 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 推回服务器。
更新 2
看来 FormsAuthentication 真的坏了。如果在对用户进行身份验证时在 cookie 上使用显式域名,请等待会话超时,然后刷新页面,FormsAuthentication 使用的生成 cookie 的方法会导致域为 null,从而导致浏览器分配一个无点域。
它需要预先为表单分配一个域才能将其分配给 cookie,这会破坏多租户系统......