有和没有指定域名的Cookie(浏览器不一致)
我注意到,在浏览器之间有一些cookie的真正的不一致之处。
这对我来说将是相当长的。
注意:我在我的主机文件“testdomain.com”中设置了一个域,这个bug在使用“localhost”的时候工作。
注2:我很好奇,知道如果这个工作在Apache / PHP上时,如果它返回一个cookie的集合,如果你通过名字检索一个cookie。
维基百科
维基百科指出: http : //en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path
域和path
Cookie域和path定义了Cookie的范围 – 它们告诉浏览器,cookies应该只发送给给定域和path的服务器。 如果未指定,则默认为请求的对象的域和path。
所以如果我们按下:
Response.Cookies.Add(new HttpCookie("Banana", "2") { });
我们应该从所请求的对象中获得一个域作为域的cookie,在这种情况下,它应该是“testdomain.com”。
W3
W3在cookies的规范中声明: http : //www.w3.org/Protocols/rfc2109/rfc2109
域=域名
可选的。 “域”属性指定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
歌剧:1个cookies
Firefox:1个cookie
Chrome:1个Cookie
正如你所看到的,Opera和IE都设置了一个不带点前缀的EXPLICIT域。
Firefox和Chrome DO都使用点前缀来设置EXPLICIT域。
如果我使用下面的代码:
Response.Cookies.Add(new HttpCookie("Banana", "2") { });
IE / Opera:两者具有完全相同的结果,域没有点前缀。
有趣的是,Firefox和Chrome都创build没有点前缀的cookie。
(我清除了所有的cookies并再次运行代码)
火狐:
铬:
有趣的位
这是它变得有趣的地方。 如果我像这样一个接一个地写cookies:
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 – 2cookies设置(浏览器见1):
歌剧-2cookies套装(浏览器见1):
Firefox – 2个Cookie设置和浏览器见2 !:
Chrome – 2cookies套装和浏览器见2 !:
现在你可能想知道所有这一切。
好:
- 当您通过C#中的名称访问cookie时,会为您提供1个Cookie。 (具有该名称的第一个cookie)
- 浏览器将所有cookie发送到服务器
- 浏览器不会发送cookie以外的任何信息。 (这意味着服务器不关心域)
- 如果您通过索引检索它们,您可以访问同名的两个cookie
问题…
我们必须改变我们的身份validation,以便在我们推送时指定cookie中的域名。
这打破了Chrome和Firefox,用户不再能够login,因为服务器会尝试validation旧的身份validationcookie。 这是因为(从我的理解),它使用authenticationCookie名称来检索cookie。
即使是有两个cookies,第一个被检索,这恰好是旧的,身份validation失败,用户没有login。有时正确的cookie是第一个在列表中,身份validation成功…
最初我们通过推送一个旧域的cookie来解决这个问题。 这在Chrome和Firefox中起作用。
但是现在它破坏了IE / Opera,因为两个浏览器都不关心这个域名,而只是根据这个名字比较这个cookie。
我的结论是,cookie上的域名完全是浪费时间。
假设我们必须指定域,并且我们不能依靠用户来清除他们的浏览器caching。 我们如何解决这个问题?
更新:
挖掘.NET如何签署用户。
if (FormsAuthentication._CookieDomain != null) { httpCookie.Domain = FormsAuthentication._CookieDomain; }
看起来,Forms身份validation完全可能推送过期的Auth cookie,这与用户通过身份validation的cookie完全无关。 它不使用当前的Auth Cookie域。
无论如何它不能使用它,因为域不会被cookie推回到服务器。
更新2
看来FormsAuthentication真的被打破了。 如果在对用户进行身份validation时使用cookie上的显式域名,请等待会话超时,然后刷新页面,生成由FormsAuthentication使用的cookie的方法结果为null,这会导致浏览器分配一个无点域名
它要求表单被分配一个域,它被分配到cookie,这打破了多租户系统…
@ WilliamBZA的build议帮助解决了最初的问题,但后来注销/会话超时错误,导致在创build一个隐含的域cookie的cookie使我得出结论,解决scheme是…
不要在.NET中使用明确的cookies …永远
有太多的问题,肯定可以通过明确的表单/域名,Cookie /域名等来解决。确保正确的域名无处不在。 但是,如果您的应用程序托pipe多个域或多租户,那么它就成了问题。
经验教训。 不要使用明确的cookies。
无法帮助为什么 cookie被区别对待,但是一个快速的解决办法是每个子应用程序使用不同的cookie名称,而不是使用cookie的域名。
在表单身份validation的情况下,更改ASPXAUTH cookie的名称。