C# 带有和不带有指定域的 Cookie(浏览器不一致)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10751813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 15:06:37  来源:igfitidea点击:

Cookies with and without the Domain Specified (browser inconsistency)

c#cookiescross-browser

提问by Phill

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

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

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

这将是相当长的所以请耐心等待。

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

注意:我在我的主机文件中设置了一个名为“testdomain.com”的域,这个错误在使用“localhost”时不会起作用。

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.

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

Wikipedia

维基百科

Wikipedia states that: http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path

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

Domain and Path
The cookie domain and path define the scope of the cookie—they tell the browser that cookies should only be sent back to the server for the given domain and path. If not specified, they default to the domain and path of the object that was requested.

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

So if we push down:

所以如果我们向下推:

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

});

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

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

W3

W3

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

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

Domain=domain

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

域=域

可选的。Domain 属性指定 cookie 对其有效的域。 明确指定的域必须始终以点开头。

So if we push down:

所以如果我们向下推:

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

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

我们明确地按下了主机名,我们应该在 cookie 上设置一个域名,该域名将以点为前缀,在这种情况下,它应该是“.testdomain.com”。

It also states what's on Wikipedia:

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

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

域 默认为请求主机。(注意 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
});

This is the results:

这是结果:

IE9: 1 cookie

IE9:1 个饼干

IE with 1 cookie and domain explicitly set

具有 1 个 cookie 和域的 IE 显式设置

Opera: 1 cookie

歌剧:1个饼干

Opera with 1 cookie and domain explicitly set

Opera 明确设置了 1 个 cookie 和域

Firefox: 1 cookie

火狐:1 个 cookie

Firefox with 1 cookie and domain explicitly set

Firefox 明确设置了 1 个 cookie 和域

Chrome: 1 cookie

铬:1个饼干

Chrome with 1 cookie and domain explicitly set

Chrome 明确设置了 1 个 cookie 和域

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

如您所见,Opera 和 IE 都设置了一个没有点前缀的 EXPLICIT 域。

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

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

If I use the following code:

如果我使用以下代码:

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

});

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

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

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

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

(I cleared all cookies and ran the code again)

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

Firefox:

火狐:

Firefox with 1 cookie and domain explicitly set

Firefox 明确设置了 1 个 cookie 和域

Chrome:

铬合金:

Chrome with 1 cookie and domain explicitly set

Chrome 明确设置了 1 个 cookie 和域

INTERESTING BIT

有趣的位

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

这就是它变得有趣的地方。如果我像这样一个接一个地写 cookie:

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

});

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

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

Here's what i've observed:

这是我观察到的:

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

在 IE/Opera 中,最后一个 cookie 集是使用的 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.

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

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

另一方面,Chrome 和 Firefox,看到不止 1 个 cookie:

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

我编写了以下 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>

These are the results:

这些是结果:

IE - 2 cookies set (browser sees 1):

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

IE - 2 cookies set, the outcome

IE - 2 cookie 设置,结果

Opera - 2 cookies set (browser sees 1):

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

enter image description here

在此处输入图片说明

Firefox - 2 cookies set and browser sees 2!:

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

enter image description here

在此处输入图片说明

Chrome - 2 cookies set and browser sees 2!:

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

enter image description here

在此处输入图片说明



Now you're probably wondering wtf all this is.

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

Well:

好:

  1. When you access the cookie by Name in C#, it gives you 1 cookie. (the first cookie that has that name)
  2. The browser sends ALL cookies to the server
  3. The browser doesn't send any information other than the key/value of the cookie. (this means the server doesn't care about the domain)
  4. You can access both cookies of the same name, if you retrieve them by index
  1. 当您在 C# 中按名称访问 cookie 时,它​​会为您提供 1 个 cookie。(第一个具有该名称的 cookie)
  2. 浏览器将所有 cookie 发送到服务器
  3. 除了 cookie 的键/值之外,浏览器不会发送任何信息。(这意味着服务器不关心域)
  4. 如果您通过索引检索它们,您可以访问同名的两个 cookie

The problem...

问题...

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

当我们按下它时,我们必须更改我们的身份验证以在 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.

这破坏了 Chrome 和 Firefox,用户无法再登录,因为服务器会尝试验证旧的 auth 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,第一个被检索,恰好是旧的,身份验证失败,用户未登录。有时正确的 cookie 是列表中的第一个,身份验证成功......

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

最初,我们通过推送带有旧域的 cookie 使其过期来解决此问题。这在 Chrome 和 Firefox 中有效。

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

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

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

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

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?

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

Update:

更新:

Digging into how .NET signs a user out.

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

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

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,这与用户身份验证所用的 cookie 完全无关。它不使用当前 Auth Cookie 的域。

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

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

Update 2

更新 2

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.

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

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

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

采纳答案by Phill

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

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

Don't use Explicit cookies in .NET... ever

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

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.

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

Lesson is learnt. Don't use explicit cookies.

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

回答by WilliamBZA

Can't help with whythe cookies are treated differently, but a quick fix would be to use a different cookie name per sub-application rather than using the domain of the cookie.

无法解释为什么cookie 被区别对待的原因,但快速解决方法是为每个子应用程序使用不同的 cookie 名称,而不是使用 cookie 的域。

In the case of Forms Authentication, change the name of the ASPXAUTH cookie.

在表单身份验证的情况下,更改 ASPXAUTH cookie 的名称。