【问题标题】:ASP.NET Subdomain Cookie (parent and one subdomain)ASP.NET 子域 Cookie(父域和一个子域)
【发布时间】:2011-01-11 11:08:27
【问题描述】:

我有一个包含多个子域 subone.parent.com、subtwo.parent.com 的应用。

我在 parent.com/login 上有一个登录页面。当用户登录时,我会根据他们所属的域将他们重定向到正确的域。这工作正常。

FormsAuthenticationTicket ticket = new FormsAuth...
string encTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
cookie.Domain = subone.parent.com
Response.Cookies.Add(cookie)

这会正确验证 subone.parent.com 的用户,而不是 subtwo.parent.com。但是我想做以下事情。

如果用户返回 parent.com,我想知道他们已登录并将他们重定向回 subone.parent.com。

是否有实现此目的的最佳实践?还是我必须为 parent.com 设置另一个 cookie?

如果重要的话,我正在使用 asp.net mvc。

谢谢!

【问题讨论】:

    标签: asp.net asp.net-mvc forms-authentication


    【解决方案1】:

    您可以像尝试做的那样跨域共享 cookie,但这并不简单,例如 here

    另一种选择是将 cookie 设置为“.parent.com”,而不是明确指定子域,并使用 cookie 存储子域的详细信息。然后,您可以从您的任何子域(以及假设其 www.parent.com 的父域)访问 cookie。

    如果您使用 MVC,您可以轻松创建自定义过滤器并添加到 www.parent.com 控制器以检查 cookie 是否存在,如果存在则重定向到 cookie 指定的子域。过滤器的更多细节here

    【讨论】:

    • 我认为您的第二个选项可能有效。我将域设置为父级。我已将子域添加到 FormsAuthTicket 用户数据中。我创建了一个 CustomIdentity,它将在 IsAuthenticated 上根据用户数据检查当前域。你怎么看?
    【解决方案2】:

    我会为显式域设置 cookie,因为这会维护该特定域的 cookie 中的任何安全信息。您还可以在 *.parent.com 级别添加一个未加密的 cookie,其中包含有关哪些域已通过身份验证的信息。尽管不使用时间戳并在应用程序之间建立逻辑连接,但没有真正的方法可以将它们联系在一起(即 - sub2 的会话超时时间为 20 分钟,因此如果域 + 有效时间戳出现在父 cookie 中,它将是有效的,但是这是业务逻辑)。

    我不确定域之间断开连接背后的原因,但您实际上可能更喜欢在加密文本后面有一个加密文本的单个 cookie。例如:

    1) Sub1 登录,将 parent.com cookie 设置为有效。将一段用户数据发送到身份验证 Web 服务。

    2) 身份验证服务将 sub1 识别为发送者,对用户数据进行加密,并将其添加到自定义 cookie 对象中。

    3) 自定义 cookie 对象在唯一拆分字符(或序列)上构造复合字符串,并使其可用于服务方法。

    4) 服务使用表单加密,加密整个票证并将其发送回原始登录。

    这样,每台服务器都可以对全局票证进行解密,但每条数据都将使用通用算法加密,但使用基于服务器的 salt。所以如果 sub2 尝试从 sub1 读取 cookie 数据,它会得到加密版本而不是原始数据。

    【讨论】:

    • 谢谢,如果我在 .parent 级别添加未加密的用户 cookie,是否不能更改/欺骗以允许访问其他子域?
    • @Paul:有点。我建议使用 2 级加密。第一个是默认的 FormsAuthentication 加密,它使您的整个 cookie 仅对 *.parent.com 域保密。第二种是应用于 cookie 的每个私有部分的内部加密,其盐仅在主服务器和单个服务器之间知道。每个子域都可以访问整个 cookie,但它们无法解密属于不同子域的部分。 FormsAuthentication.IsAuthenticated 会产生一个“真”值。
    • @Paul:继续——记住这一点,您需要通过验证实际 cookie 本身中的数据的东西来增强此检查。 IsAuthenticated && MyCookieData.IsValid(ticket) 或类似的东西。
    【解决方案3】:

    您可以在所有子域上共享同一个会话。这就是我们用来完成的代码:-)

    void MasterPage_Unload(object sender, EventArgs e)
    {
       ///ASP.NET uses one cookie per subdomain/domain,
       ///we need one cookie for _all_ subdomains.
       if (Context.Response.Cookies["ASP.NET_SessionId"] == null)
          return;
    
       var sessionCookie = new HttpCookie("ASP.NET_SessionId", Context.Session.SessionID);
       sessionCookie.Domain = ".yourdomain.com" ; 
       Context.Response.SetCookie(sessionCookie);
     }
    

    Page_Load 方法里面是:

     Unload += MasterPage_Unload;
    

    效果很好:-)

    罗伯特

    【讨论】:

    • 谢谢罗伯特,但我不希望用户在所有子域上都经过身份验证,只需要一个子域和根域。
    • 我们在使用这个解决方案时遇到了一个严重的问题:它使OutputCache 无法在所有使用该代码的 MasterPage 的页面上工作。 This solution here 让 OutputCache 像魅力一样工作。
    猜你喜欢
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2011-04-21
    • 1970-01-01
    相关资源
    最近更新 更多