跨子域共享 ASP.NET cookie

Posted

技术标签:

【中文标题】跨子域共享 ASP.NET cookie【英文标题】:Sharing ASP.NET cookies across sub-domains 【发布时间】:2011-11-27 05:25:21 【问题描述】:

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

一旦我在每个站点上通过了身份验证,我就会查看后续请求中包含的 cookie,它们对于每个站点都是相同的。

但是,如果我登录到第一个站点,然后导航到另一个站点,我希望站点 1 的 cookie 会随请求一起发送到站点 2,但事实并非如此。这是我的 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 中,因为它只在客户端上需要)。 我已确保每个表单的设置都相同 我已确保我的机器密钥设置在两个 Web 配置中是相同的。

我不知道为什么这不起作用。据我所知,当客户端都使用相同的身份验证 cookie 时,客户端会将其发送到一个子域而不是另一个子域时,cookie 包含什么?

如果您想查看更多信息,请发表评论。我已经为此苦苦挣扎了两天了。根据this article,这应该可以工作。

更新:添加了代码

这是我的身份验证配置文件设置。这在两个站点中都使用。

<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\AppData\Roaming\Microsoft\Windows\Cookies

当我将 cookie 添加到站点的响应中时,它会添加到此目录中... C:\Users\jreddy\AppData\Roaming\Microsoft\Windows\Cookies\Low

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

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

【问题讨论】:

domain="mydomain.com" 应该是 domain=".mydomain.com" (注意前导句点) 对我来说,我的问题是我忘记了 Web.config 调试转换 -_- 【参考方案1】:

在两个子域网站的每个Cookies中设置Domain属性为“.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

试试看

问候

【讨论】:

我的域设置是否必须是“.mydomain.com”而不是“mydomain.com”(前导域名)? 我试过了,但没有用。我还尝试创建第二个 cookie,它保存一个随机值,而不是“FormsAuthentication”cookie。我的第二个网站也没有收到它。 杰夫:是的“。”必须存在,并查看更新 1 并测试该代码,:) 我尝试了您添加的内容,几乎是逐字逐句,但仍然没有运气。最初我试图共享一个身份验证 cookie,但此时我将满足于“strName”和“value”。当我到达站点一并按照您的建议创建该 cookie 时,它​​总是在以后的请求中发送到该站点(站点 1),但站点 2 永远不会得到它。 首先,我确定这段代码是正确的并且可以工作,我在我的项目中使用它,其次,玩cookie有很多条件,所以确保你已经清除了旧的,然后确保通过在浏览器中将 cookie 的域值检查为“.mydomain.com”并过期足够的值来正确创建 cookie,然后通过我告诉你的代码读取它的最后一步......告诉我在哪一步你确实解决了这个问题。问候【参考方案2】:

添加新的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..

【讨论】:

我添加了用于两个站点的身份验证配置设置,以及 cookie 创建代码。 我尝试在 site1 中的响应中添加另一个 cookie,类似于您的。我只是将它命名为测试,给它随机值,然后确保我设置了域。设置后,以后对 Site1 的访问会给我 cookie,但对 site2 的访问不会获得 cookie。 查看此链接 15seconds.com/issue/971108.htm 或 SO 问题 - ***.com/questions/2172490/… 我已经从这两个站点中提取了样本和建议。仍然无法在 site2 中获取 cookie。 对于表单身份验证cookie,还值得一提的是,如果有多个应用程序,机器密钥应该匹配。此外,我必须显式设置compatibilityMode 才能在IIS8 中正常运行。 msdn.microsoft.com/en-us/library/…【参考方案3】:

如果您在所有子域上使用 Forms 身份验证,您只需将 domain=".mydomain.com" 属性添加到 &lt;forms&gt; 节点中的 web.config

注意.mydomain.com中的前导句点

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

【讨论】:

【参考方案4】:

我创建了一个 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();
    

【讨论】:

这行context.Request.IsLocal是什么意思? IsLocal 何时为真? 当你在 localhost 上运行应用程序时

以上是关于跨子域共享 ASP.NET cookie的主要内容,如果未能解决你的问题,请参考以下文章

使用 ASP.NET 会话状态服务跨应用程序共享会话

跨 DNN 和 ASP.net 应用程序共享身份验证、成员资格和角色

在 ASP.Net 5 / Core 中启用跨域资源共享 (CORS)

ASP.NET下跨应用共享Session和使用Redis进行Session托管

ASP.NET MVC 表单身份验证域属性在 Firefox 中中断登录

通过多个 Laravel 5 安装跨子域共享身份验证会话