带有和不带有指定域的 Cookie(浏览器不一致) [英] Cookies with and without the Domain Specified (browser inconsistency)

查看:52
本文介绍了带有和不带有指定域的 Cookie(浏览器不一致)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到浏览器之间在 cookie 方面存在一些真正的不一致.

I've noticed that there are some real inconsistencies between browsers in terms of cookies.

这会很长,所以请耐心等待.

This is going to be rather long so bear with me.

注意:我在我的主机文件中设置了一个名为testdomain.com"的域,这个bug在使用localhost"时不起作用.

Note: I've setup a domain in my host file called "testdomain.com", this bug WONT work when using "localhost".

注意 2:我很想知道这在 Apache/PHP 上是如何工作的,如果您按名称检索 cookie,如果它返回一组 cookie.

Note2: I am curious to know how this works on Apache/PHP if when you retrieve a cookie by name if it gives a collection of cookies back.

维基百科声明:http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path

域和路径
cookie 域和路径定义了范围cookie——它们告诉浏览器 cookie 应该只被发送回给定域和路径的服务器.如果没有指定,他们默认为请求对象的域和路径.

所以如果我们向下推:

Response.Cookies.Add(new HttpCookie("Banana", "2")
{

});

我们应该得到一个 cookie,使用的域是请求对象的域,在这种情况下它应该是testdomain.com".

We should get a cookie with the domain used being the domain from the requested object, in this case it should be "testdomain.com".

W3 在 cookie 规范中声明:http://www.w3.org/Protocols/rfc2109/rfc2109

W3 states in the specification for cookies: http://www.w3.org/Protocols/rfc2109/rfc2109

域=域

可选.Domain 属性指定域cookie 有效.明确指定的域必须始终启动带一个点.

Optional. The Domain attribute specifies the domain for which the cookie is valid. An explicitly specified domain must always start with a dot.

所以如果我们向下推:

Response.Cookies.Add(new HttpCookie("Banana", "1")
{
    Domain = Request.Url.Host
});

我们明确下推主机名,我们应该在 cookie 上设置一个以点为前缀的域名,在这种情况下应该是.testdomain.com".

We pushed down the host-name explicitly, we should get a domain name set on the cookie which would be prefixed with the dot, in this case it should be ".testdomain.com".

它还说明了维基百科上的内容:

It also states what's on Wikipedia:

域默认为请求主机.(注意没有点在request-host 的开头.)

Domain Defaults to the request-host. (Note that there is no dot at the beginning of request-host.)

<小时>

到目前为止和我在一起吗?


With me so far?

如果我使用第一种方法,定义一个域:

If I use the first method, defining a Domain:

Response.Cookies.Add(new HttpCookie("Banana", "1")
{
    Domain = Request.Url.Host
});

结果如下:

IE9:1 个 cookie

IE9: 1 cookie

歌剧:1 个饼干

Firefox:1 个 cookie

Firefox: 1 cookie

Chrome:1 个 cookie

Chrome: 1 cookie

如您所见,Opera 和 IE 都设置了一个不带点前缀的 EXPLICIT 域.

As you can see, both Opera and IE both set an EXPLICIT domain without the dot prefix.

Firefox 和 Chrome 都使用点前缀设置 EXPLICIT 域.

Both Firefox and Chrome DO set the EXPLICIT domain with a dot prefix.

如果我使用以下代码:

Response.Cookies.Add(new HttpCookie("Banana", "2")
{

});

IE/Opera:两者具有完全相同的结果,域没有点前缀.

IE / Opera: Both have the exact same result, the domain WITHOUT the dot prefix.

有趣的是,Firefox 和 Chrome 都创建了没有点前缀的 cookie.

Funnily enough, Firefox and Chrome both create cookies WITHOUT the dot prefix.

(我清除了所有 cookie 并再次运行代码)

(I cleared all cookies and ran the code again)

火狐:

铬:

这就是有趣的地方.如果我像这样一个接一个地写 cookie:

This is where it gets interesting. If I write the cookies one after another like so:

Response.Cookies.Add(new HttpCookie("Banana", "1")
{
    Domain = Request.Url.Host
});
Response.Cookies.Add(new HttpCookie("Banana", "2")
{

});

我个人希望浏览器中存在一个 cookie,因为我认为它基于 cookie 名称.

PERSONALLY I would expect one cookie to exist in the browser, because I assume it's based on the cookie name.

这是我观察到的:

在 IE/Opera 中,最后一个 cookie 集是使用的 cookie.这是因为 Cookie 名称和域名是相同的.

In IE / Opera, the LAST cookie set is the cookie that is used. This is because the Cookie name and Domain name are identical.

如果你明确定义一个带点的域名,两个浏览器仍然会看到1个cookie,最后一个同名的cookie.

If you explicitly define a domain name with a dot, both browser will still see 1 cookie, the last cookie of the same name.

另一方面,Chrome 和 Firefox,看到 1 个以上的 cookie:

Chrome and Firefox on the other hand, see more than 1 cookie:

我编写了以下 JavaScript 来将值转储到页面:

I wrote the following JavaScript to dump the values to the page:

<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 个):

IE - 2 cookies set (browser sees 1):

Opera - 2 个 cookie 集(浏览器看到 1 个):

Opera - 2 cookies set (browser sees 1):

Firefox - 设置了 2 个 cookie,浏览器看到了 2 个!

Firefox - 2 cookies set and browser sees 2!:

Chrome - 设置了 2 个 cookie,浏览器看到了 2 个!

Chrome - 2 cookies set and browser sees 2!:

现在你可能想知道这一切是什么.

Now you're probably wondering wtf all this is.

嗯:

  1. 当您在 C# 中按名称访问 cookie 时,它​​会为您提供 1 个 cookie.(第一个具有该名称的 cookie)
  2. 浏览器将所有 cookie 发送到服务器
  3. 浏览器不会发送 cookie 的键/值以外的任何信息.(这意味着服务器不关心域)
  4. 您可以访问同名的两个 cookie,如果您通过索引检索它们

问题...

我们不得不更改我们的身份验证,以便在我们下推时在 cookie 中指定域.

We had to change our Authentication to specify the domain in the cookie when we pushed it down.

这破坏了 Chrome 和 Firefox,用户无法再登录,因为服务器会尝试验证旧的 auth cookie.这是因为(根据我的理解)它使用身份验证 Cookie 名称来检索 cookie.

This broke Chrome and Firefox, users were no longer able to login, because the server would try authenticate the old auth cookie. This is because (from my understanding) it uses the Authentication Cookie Name to retrieve the cookie.

即使有两个 cookie,第一个被检索,恰好是旧的,身份验证失败,用户未登录.有时正确的 cookie 在列表中排在第一位,身份验证成功...

Even tho there are two cookies, the first one is retrieved which happens to be the old one, authentication fails, user isn't logged in. SOMETIMES the correct cookie is first in the list, and the authentication succeeds...

最初我们通过推送带有旧域的 cookie 使其过期来解决此问题.这适用于 Chrome 和 Firefox.

Initially we solved this by pushing a cookie with the old domain to expire it. This worked in Chrome and Firefox.

但它现在破坏了 IE/Opera,因为两个浏览器都不关心域,只根据名称比较 cookie.

But it now broke IE/Opera since both browsers don't care about the domain and only compare the cookie based on the name.

我的结论是,cookie 上的域完全是在浪费时间.

My conclusion is that the domain on a cookie is a complete utter waste of time.

假设我们必须指定域,并且我们不能依赖用户清除他们的浏览器缓存.我们如何解决这个问题?

Assuming that we must specify the domain, and we can't rely on users to clear their browser cache. How can we resolve this problem?

深入了解 .NET 如何将用户注销.

Digging into how .NET signs a user out.

if (FormsAuthentication._CookieDomain != null)
{
    httpCookie.Domain = FormsAuthentication._CookieDomain;
}

看起来表单身份验证完全有可能推送过期的身份验证 cookie,这与用户身份验证所用的 cookie 完全无关.它不使用当前 Auth Cookie 的域.

It looks like it's entirely possible for the Forms authentication to push an expired Auth cookie, that is entirely unrelated to the cookie the user is authenticated with. It doesn't use the current Auth Cookie's domain.

无论如何它都不能使用,因为域不会通过 cookie 推送回服务器.

Which it can't use anyway, since the domain isn't pushed back to the server with the cookie.

看来 FormsAuthentication 真的坏了.如果在对用户进行身份验证时在 cookie 上使用显式域名,请等待会话超时,然后刷新页面,FormsAuthentication 使用的 cookie 生成方法导致域为空,从而导致浏览器分配一个无点域.

It seems FormsAuthentication is really broken. If you use an explicit domain name on a cookie when you authenticate the user, wait for the session to timeout, then refresh the page, the method of generating the cookie used by FormsAuthentication results in the domain being null which causes the browser to assign a dotless domain.

它需要预先为表单分配一个域,以便将其分配给 cookie,这破坏了多租户系统...

It requires that Forms be assigned a domain up front for it to be assigned to the cookie, this breaks a multi-tenant system...

推荐答案

@WilliamBZA 的建议帮助解决了最初的问题,但随后导致 cookie 创建隐式域 cookie 的注销/会话超时错误让我得出了结论解决方案是...

@WilliamBZA's suggestion helped solve the initial problem, but then signout/session timeout bug that results in the cookie creating an implicit domain cookie has made me come to the conclusion that the solution is...

不要在 .NET 中使用显式 cookie...永远

问题太多了,肯定可以通过在Form/Domain、Cookie/Domain等上显式来解决.确保在任何地方都使用正确的域.但是,如果您的应用程序托管多个域或多租户,那么问题就太大了.

There are far too many problems, sure they can be solved by being explicit on the Form/Domain, Cookie/Domain, etc. To ensure that the correct domain is used everywhere. But if your application hosts multiple domains or is multi tenant, then it just becomes too problematic.

吸取了教训.不要使用显式 cookie.

Lesson is learnt. Don't use explicit cookies.

这篇关于带有和不带有指定域的 Cookie(浏览器不一致)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆