跨子域共享ASP.NET cookie

时间:2011-09-28 21:09:44

标签: asp.net authentication cookies

我有两个网站,都位于同一个网域,但具有不同的子网域 site1.mydomain.com site2.mydomain.com

一旦我对每个网站进行了身份验证,我会查看后续请求中包含的Cookie,并且每个网站的Cookie都相同。

但是,如果我登录到第一个站点,然后导航到另一个站点,我希望我的站点1的cookie与请求一起发送到site2,但事实并非如此。以下是我的cookie的属性。

登录Site1,此cookie存在

Name = MySite 
Domain = 
Has Keys = False 
HttpOnly = False 
Path = / 
Value = 1C41854066B03D8CC5679EA92DE1EF427DAC65D1BA0E672899E27C57245C1F0B7E93AB01B5563363AB4815A8F4BDE9D293FD261E03F8E60B8497ABBA964D8D315CCE1C8DD220C7176E21DC361935CF6 
Expires = 1/1/0001 12:00:00 AM 

登录Site2后,这些cookie就存在了。

Name = MySite 
Domain = 
Has Keys = False 
HttpOnly = False 
Path = / 
Value =    C8C69F87F993166C4D044D33F21ED96463D5E4EB41E1D986BF508DA0CBD5C2CA7D782F59F3BC96871108997E899FF7401C0D8615705BDB353B56C7E164D2302EE6731F41705016105AD99F4E0578ECD2 
Expires = 1/1/0001 12:00:00 AM 

我已经在每个域上设置了域名(不会显示在请求cookie中,因为它只在客户端上需要)。 我确保我的每个表单设置都相同 我确保我的机器密钥设置在两个网络配置中都是相同的。

我不知道为什么这不起作用。什么是cookie包含客户端将为一个子域而不是另一个子域发送它,因为他们都使用相同的身份验证cookie到目前为止?

如果您想了解更多信息,请发表评论。我已经在这两天苦苦挣扎了。根据{{​​3}},这应该有效。

更新代码

这是我的身份验证配置文件设置。这用于两个站点。

<authentication mode="Forms">
    <forms loginUrl="~/Account/LogOn"
       defaultUrl="~/Home/Index"
       name="MySite" 
       protection="All" 
       path="/" 
       domain="mydomain.com" 
       enableCrossAppRedirects="true" 
       timeout="2880" 
/>

这是我在Site1中创建cookie的代码。

//Add a cookie that the Site2 will use for Authentication
var cookie = FormsAuthentication.GetAuthCookie(userName, true);
cookie.Name = "MySite";
cookie.HttpOnly = false;
cookie.Expires = DateTime.Now.AddHours(24);
cookie.Domain = "mydomain.com"; 
HttpContext.Response.Cookies.Add(cookie);
HttpContext.Response.Redirect(site2Url,true);

更新2:

我在测试时发现了一些奇怪的东西。当我为site1的响应添加一个cookie时,它会被添加到这个目录中......     C:\ Users \用户jreddy \应用程序数据\漫游\微软\的Windows \饼干

当我向网站的响应添加cookie时,它会被添加到此目录中...     C:\ Users \用户jreddy \应用程序数据\漫游\微软\的Windows \饼干\低

这可能是我的问题。可能是我的某个网站包含在本地Intranet区域中吗?

更新3:发现问题,解决方案未知 似乎我的问题与我的第二个站点是本地Intranet区域的一部分有关。如果我使用Firefox访问Site1它可以工作,但我必须输入我的Windows凭据。如果我通过IE浏览器,我的凭据会自动获取,但site2无法读取cookie。我可以在另一个问题上问这个问题。

4 个答案:

答案 0 :(得分:16)

在两个子域名网站的每个Cookie中将域的属性设置为“.mydomain.com”

喜欢

Response.Cookies["test"].Value = "some value";
Response.Cookies["test"].Domain = ".mysite.com";

更新1

在网站

HttpCookie hc = new HttpCookie("strName", "value");
hc.Domain = ".mydomain.com"; // must start with "."
hc.Expires = DateTime.Now.AddMonths(3);
HttpContext.Current.Response.Cookies.Add(hc);

在网站B

HttpContext.Current.Request.Cookies["strName"].Value

试一试

此致

答案 1 :(得分:9)

添加新Cookie并指定域名

HttpCookie cookie = new HttpCookie("cookiename", "value");
cookie.Domain = "domain.com";

对于表单身份验证,请在web.config

中设置
<forms name=".ASPXAUTH" 
       loginUrl="login.aspx" 
       protection="All" 
       timeout="30" 
       path="/" 
       requireSSL="false" 
       domain="domain.com">
</forms>

所有子域都可以访问cookie。

为了使每个域解密cookie,所有web.config文件必须使用相同的加密/解密算法和密钥。 (how to create a machine key

示例:

// do not wrap these values like this in the web.config
// only wrapping for code visibility on SO
<machineKey  
  validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75
                 D7AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281
                 B"             
  decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719
                 F"
  validation="SHA1"
  decryption="AES"
/>

为了便于部署,这些值可以存储在单独的文件中:

<machineKey configSource="machinekey.config"/>

For added security you can also encrypt the machine key for further protection.

答案 2 :(得分:4)

如果您在所有子域上使用表单身份验证,则只需将domain=".mydomain.com"属性添加到<forms>

中的web.config节点即可

请注意.mydomain.com

中的前导期

这种简单的更改本身将使您的身份验证cookie在所有子域中都有效;无需手动设置任何cookie。

答案 3 :(得分:1)

我已经创建了一个HttpContext扩展方法,它将编写一个子域安全cookie。

Blog post and discussion

public static class HttpContextBaseExtenstions
{
    public static void SetSubdomainSafeCookie(this HttpContextBase context, string name, string value)
    {
        var domain = String.Empty;

        if (context.Request.IsLocal)
        {
            var domainSegments = context.Request.Url.Host.Split('.');
            domain = "." + String.Join(".", domainSegments.Skip(1));
        }
        else
        {
            domain = context.Request.Url.Host;
        }

        var cookie = new HttpCookie(name, value)
        {
            Domain = domain
        };

        context.Response.SetCookie(cookie);
    }
}

// usage
public class MyController : Controller
{
    public ActionResult Index()
    {
        this.Context.SetSubdomainSafeCookie("id", Guid.NewGuid().ToString());
        return View();
    }
}