【问题标题】:Why is ASP.NET forms authentication setting cookies on a static image request?为什么 ASP.NET 表单身份验证在静态图像请求上设置 cookie?
【发布时间】:2011-05-11 14:54:22
【问题描述】:

我有一个 ASP.NET (MVC) 网站,它提供静态内容(图像)以及来自同一域的动态内容。该站点使用表单身份验证,并具有登录控制器。人们发现自己以随机间隔登录或退出时出现了一些非常奇怪/不规则的问题,我们已将其归结为反向代理缓存图像文件的问题,该图像文件具有设置 cookie 响应标头授权饼干。缓存后,每个人都会获得相同的身份验证 cookie,这会导致一些非常奇怪的结果。

我的问题是 - 图片首先如何获得 set-cookie 标头?什么是 ASP.NET 表单身份验证模块会导致此问题 - 它肯定会在主要 HTML 内容响应上设置 cookie。我知道 auth cookie 然后与所有后续请求一起发送到域,但我无法弄清楚 cookie 是如何设置的。

(顺便说一句,这个问题也可能是至少两个存在类似问题的现有大型电子商务网站的罪魁祸首,没有解决方案,所以这是一个很好的解决方案。

响应如下所示(取自 fiddler)。

HTTP/1.1 200 OK
Cache-Control: public, max-age=86400,max-age=86400
Content-Type: image/png
Last-Modified: Thu, 04 Nov 2010 16:00:52 GMT
Accept-Ranges: bytes
ETag: "0528474397ccb1:0"
Server: Microsoft-IIS/7.5
Set-Cookie: my-auth-cookie=6BC25F1EF71989466A48C0120E7739E; path=/; HttpOnly
Date: Wed, 17 Nov 2010 17:15:08 GMT
Content-Length: 15790

更新:附加信息 - 我们在 Win2008 R2、64 位上使用 IIS 7.5,并且该应用在使用集成管道/.net 4 的应用池下运行。

更新 2:我不是在寻找解决问题的方法,我们已经有了。我正在寻找这个问题的答案,这就是为什么它首先发生?请不要回答告诉我有关子域或 cookie 的工作原理!

更新3:添加请求:

GET https://www.example.com/sprite.png HTTP/1.1
Host: www.example.com
Connection: keep-alive
Cache-Control: no-cache
Pragma: no-cache
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: my-auth-cookie=6BC25F1EF71989466A48C0120E7739E;

【问题讨论】:

  • +1,非常有趣的问题。 @Hugo,你能重现这种行为还是随机的?
  • @Hugo,您是否在您的网站上强制执行 SSL,因为我注意到此 cookie 设置时没有 secure 标志?
  • 您的表单身份验证设置是什么?我尝试使用slidingExpirationtimeout 属性来重现它。当表单身份验证需要重新设置 cookie 过期日期时,来自静态文件的响应确实添加了 set-cookie 标头。但是,该 set-cookie 标头还包含一个 expires 指令,这与您的情况不同。
  • 直接来自 MSDN (hrb.fm/bsGes3):“如果发出请求并且超过一半的超时间隔已经过去,则滑动到期会重置有效身份验证 cookie 的到期时间。”这里的杀手级问题是这是否适用于在请求静态资源(不进行其他处理)时收到的 cookie,鉴于集成管道的性质,我认为答案是肯定的。接下来的问题是是否可以为非 ASP.NET 资源禁用 FormsAuth 模块。
  • IIS7+ 具有路由静态内容的能力(您无疑知道),并且表单身份验证显然是运行时本身的托管代码部分。因此,假设在集成管道模式下,如果启用,它只是被检查/运行是合乎逻辑的。你在 web.config 中有这个设置吗?

标签: asp.net-mvc iis forms-authentication reverse-proxy


【解决方案1】:

我怀疑这实际上并不是 .NET 本身的问题,而问题的关键实际上是反向代理。

从经过表单验证的路径提供静态内容时,与您的连接关联的 cookie 将随之发送。 因此,如果您以用户 X、会话 1 的身份登录并获取图像 foo.png,则您的反向代理会看到 PNG 文件带有表明可以缓存的标头。

下次请求该文件时,反向代理会直接提供该文件,以及上次获取该文件时与该文件关联的 cookie。

作为一个实验,我建议设置反向代理以关闭它的缓存功能,看看问题是否仍然存在。

如果您确实需要反向代理来缓存内容 - 那么我建议您查看是否可以告诉代理忽略缓存文件的 cookie,或将文件移动到另一个无 cookie/无身份验证的域.

【讨论】:

  • 威尔,你说的很对,这就是我们在生产中已经解决的问题。对于社区来说,这更像是一个关于它为什么会发生的问题(在静态内容上设置 cookie)。将 IIS 和 ASP.NET 捆绑在一起在当时听起来可能是个好主意,但事实证明它在生产场景中确实很痛苦(我有另一个关于身份验证选项的 serverfault 悬而未决的问题)。
  • 嗨雨果,再次 - 我不认为 .NET / IIS 直接是问题所在。正如我所提到的,从等式中删除反向代理,如果我是对的 - 问题就消失了。如果我错了,那就是更深层次的东西。
【解决方案2】:

对我来说似乎是 IIS 中的错误。我将编写一些稻草人代码,看看我是否完全理解发生了什么并发布结果。我还将在 IIS 7 和 IIS 7.5 上对其进行测试,看看它是否不同。

似乎一个请求不应该获得与前一个请求相关联的任何 cookie(我们的网站上没有任何缓存代理,这发生在我们的内部网络上,所以我的结论是 IIS 是在某处做)。

--欧文

【讨论】:

  • 好吧,无法在一个简单的稻草人示例中重现(带有一堆图像的网页;另一个设置 cookie)。没办法,没有任何图像如何从第二台机器设置cookie... FWIW
【解决方案3】:

因为您可以使用表单身份验证来保护静态内容。

【讨论】:

  • 这如何回答这个问题?请参阅我在@Zain Shaikh 答案上留下的评论。
【解决方案4】:

自己回答这个问题以结束问题并防止进一步更新。

我看到的行为的根本原因是集成管道在静态文件(css、图像、js)上设置了 cookie - 请参阅评论线程以获取更多详细信息。

当我们将静态内容移动到生产/登台环境中的不同主机时解决了这个问题。

【讨论】:

    【解决方案5】:

    默认情况下,浏览器会随 same domain 上的每个请求发送 cookie。

    简单的解决方案是将您的图像移动到其他域,例如 youtube 有一个域 http://s.ytimg.com/yt/img/watch/ 来保存所有图像。

    【讨论】:

    • 你没看问题吗?你没看到Set-Cookie 响应头吗?这是设置一个 cookie,而不是客户端通过请求中的 Cookie 标头传递它。
    猜你喜欢
    • 2012-07-12
    • 2014-04-01
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多