2010-01-31 93 views
11

我有一个应用程序与多个子域subone.parent.com,subtwo.parent.com。ASP.NET子域Cookie(父和一个子域)

我在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工作,如果它很重要。

谢谢!

回答

5

您可以像跨越域一样共享Cookie,但它不是直截了当的,例如here

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

如果你使用MVC,你可以很容易地创建一个自定义过滤器,并添加到www.parent.com控制器来检查cookie的存在,如果是这样重定向到cookie指定的子域。过滤器的进一步细节here

+0

我想你第二这里的选项可能工作。我将域设置为父级。我已将该子域添加到FormsAuthTicket用户数据。我创建了一个CustomIdentity,它将在IsAuthenticated中根据用户数据检查当前域。你怎么看? – Paul 2010-02-01 16:24:22

+0

15秒的链接似乎不应该去它应该在的地方.. – 2017-04-25 15:31:40

0

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

我不确定域之间断开连接的原因,但实际上您可能更喜欢使用加密文本后加密文本的单个cookie。 EG:

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

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

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

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

这样每个服务器将能够解密全局票证,但是每个数据片段将使用通用算法加密,但是基于服务器的盐被加密。所以如果sub2尝试从sub1读取cookie数据,它会得到加密版本而不是原始数据。

+0

谢谢,如果我在.parent级别添加未加密的用户cookie不能被更改/欺骗以允许访问其他子域? – Paul 2010-02-01 15:48:23

+0

@Paul:分类。我建议2级加密。第一种是默认的FormsAuthentication加密,它可以将整个Cookie保密为* .parent.com域。第二种是应用于Cookie的每个私有部分的内部加密,其中盐只有在主服务器和个人服务器之间才知道。每个子域都可以访问整个cookie,但他们将无法解密属于不同子域的部分。 FormsAuthentication.IsAuthenticated会导致一个“true”值。 – 2010-02-01 16:09:53

+0

@Paul:继续 - 考虑到这一点,您需要用验证实际cookie本身数据的东西来增强此检查。 IsAuthenticated && MyCookieData.IsValid(票)或类似的东西。 – 2010-02-01 16:10:45

0

您可以在所有子域上共享相同的会话。这是我们用来完成Page_Load方法里面那个:-)

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); 
} 

代码:

Unload += MasterPage_Unload; 

它的伟大工程:-)

罗伯特

+0

感谢Robert,但我不希望用户在所有子域上进行身份验证,只有一个和根。 – Paul 2010-02-01 15:45:54

+0

我们遇到了这个解决方案的一个严重问题:它保持'OutputCache'在所有使用该代码的MasterPage的页面上工作。 [此解决方案](http://stackoverflow.com/a/2088853/177710)使OutputCache像一个魅力一样工作。 – Oliver 2012-01-24 22:44:07