FormsAuthentication.SetAuthCookie没有设置路径或域?

时间:2011-07-14 15:25:51

标签: asp.net cookies forms-authentication

我有一个网络应用程序可以安装在很多域和路径上。

所以:

  • client1Name。{mySite.com}
  • client2Name。{mySite.com}
  • 演示。{mySite.com} / prospect1Name
  • 演示。{mySite.com} / prospect2Name
  • 演示。{mySite.com} / prospect3Name

相同代码的所有单独的应用程序实例。

问题是,如果客户端登录 client1Name。{mySite.com} ,则访问其他网站之一,他们的浏览器将发送身份验证cookie。

在所有情况下,FormsAuthentication.SetAuthCookie都未设置PathDomain

我期望的是:

  • client1Name。{mySite.com} - Domain = client1Name。{mySite.com} Path = /
  • client2Name。{mySite.com} - Domain = client2Name。{mySite.com} Path = /
  • demo。{mySite.com} / prospect1Name - Domain = demo。{mySite.com} Path = / prospect1Name
  • demo。{mySite.com} / prospect2Name - Domain = demo。{mySite.com} Path = / prospect2Name
  • demo。{mySite.com} / prospect3Name - Domain = demo。{mySite.com} Path = / prospect3Name

我可以手动覆盖.Net的行为以显式设置这些,但我不确定为什么我需要 - 确保这应该是设置身份验证cookie时的默认行为,或者至少是一个可以在没有重新设置的情况下设置的选项 - 写大块的。

我错过了什么吗?有没有办法让FormsAuthentication.SetAuthCookie设置PathDomain

如果不是,动态阅读最佳PathDomain的最佳方式是什么?相同的代码必须在所有站点上运行,我不想再添加配置密钥。

更新

这是我目前的解决方案:

// replacement for FormsAuthentication.SetAuthCookie(user.UserName, false);
// as that fails to limit the cookie by domain & path and fails.

var cookie = FormsAuthentication.GetAuthCookie(username, false);
cookie.HttpOnly = true;
cookie.Path = this.Request.ApplicationPath;
cookie.Secure = string.Equals("https", this.Request.Url.Scheme, StringComparison.OrdinalIgnoreCase);

// the browser will ignore the cookie if there are fewer than two dots
// see cookie spec - http://curl.haxx.se/rfc/cookie_spec.html
if (this.Request.Url.Host.Split('.').Length > 2)
{
    // by default the domain will be the host, so www.site.com will get site.com
    // this may be a problem if we have clientA.site.com and clientB.site.com
    // the following line will force the full domain name
    cookie.Domain = this.Request.Url.Host;
}

this.Response.Cookies.Add(cookie);

然而,对于FormsAuthentication.SetAuthCookie应该能做的事情,这似乎有很多变通方法。这真的是最好的方式吗?

2 个答案:

答案 0 :(得分:8)

我不得不做很多挖掘,但看起来FormsAuthentication.SetAuthCookie不支持这一点的原因是因为它不应该 - IIS应该从不在身份验证Cookie上设置路径,这就是原因......

Cookie路径区分大小写,因此:

  • http://site/path
  • http://site/PATH

浏览器有两种不同的Cookie - 其中没有一种(IE,FX,Safari,Opera或Chrome)会将/PATH的Cookie发送到/path,反之亦然。

IIS 不区分大小写,但始终会将URL重置为ASP应用程序名称的大小写。

这意味着如果IIS应用程序被称为“PATH”并且用户转到http://site/path,那么它们将被重定向到IIS / ASP.Net上的http://site/PATH/LogOn?ReturnUrl=/path登录

成功登录后,用户会被重定向回指定的ReturnUrl,因此:

  1. 用户转到http://site/path
  2. 由IIS
  3. 发送到http://site/PATH/LogOn?ReturnUrl=/path
  4. 输入登录详细信息并提交
  5. 响应将Cookie设置为/PATH,将位置设置为/path(由ReturnUrl定义)
  6. 重定向回http://site/path
  7. 浏览器无法识别/path,它只有/PATH的Cookie,因此不会发送任何内容!
  8. 没有Cookie发送到应用程序,因此它会重定向回http://site/PATH/LogOn?ReturnUrl=/path
  9. 转到第2步并重复。
  10. 如果用户http://site/path作为他们永远无法登录的应用程序的网址,则会给用户带来问题。

    除此之外,如果他们已经登录http://site/PATH并收到一个网址,比如发送一封电子邮件给http://site/path/resource/id,他们就会被要求重新登录,不会能够走上新的道路。

    这意味着除非您需要/PATH/path是完全不同的站点(不太可能在某些仅UNIX环境之外),否则不应在身份验证cookie上设置路径属性。

答案 1 :(得分:3)

Cookie在域级别设置并且是静态的。默认情况下,FormsAuthentication使用TLD进行设置,在本例中为{mySite.com}。为了使其具体化,您必须告诉它使用client1Name.{mySite.com}。但是,在这样做时,您会将cookie限制为该特定子域,并且子域client2Name将无法再访问该cookie。

Cookie的路径限制了Cookie适用的子文件夹。对于FormsAuthentication,再次将默认值设置为根/。您可以手动将其设置为其他内容,但再次通过将其设置为/prospect1Name,所有其他文件夹都会立即失去对cookie的访问权限。

我不确定您尝试使用这些约束生成什么行为,但cookie不太可能是适当的工具。使用域名进行操作会限制您的身份验证控件的有效性(除非您正在尝试这样做)。