繁体   English   中英

跨子域共享 ASP.NET cookie

[英]Sharing ASP.NET cookies across sub-domains

我有两个站点,都在同一个域上,但具有不同的子域。

  • site1.mydomain.example
  • site2.mydomain.example

一旦我在每个站点上通过了身份验证,我就会查看后续请求中包含的 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 包含什么?

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

添加的代码

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

<authentication mode="Forms">
    <forms loginUrl="~/Account/LogOn"
       defaultUrl="~/Home/Index"
       name="MySite"
       protection="All"
       path="/"
       domain="mydomain.example"
       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.example";
HttpContext.Response.Cookies.Add(cookie);
HttpContext.Response.Redirect(site2Url,true);

更新 2:

我在测试时发现了一些奇怪的东西。 当我将 cookie 添加到 site1 的响应中时,它会添加到此目录中... 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。 我可能会在另一个问题中问这个问题。

在两个子域网站的每个 Cookie 中,将 Domain 的属性设置为.mydomain.example 喜欢:

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

在站点 A:

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

在站点 B:

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

添加新的cookie并像这样指定域

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

对于表单身份验证,请在 web.config 中设置此项

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

所有子域都可以访问 cookie。

为了让每个域解密 cookie,所有 web.config 文件必须使用相同的加密/解密算法和密钥。 如何创建机器密钥

例子:

// 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"/>

为了增加安全性,您还可以加密机器密钥以进一步保护。 .

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

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

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

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

博客文章和讨论

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM