【问题标题】:ASP.NET cross subdomain cookies not being attached to requestASP.NET 跨子域 cookie 未附加到请求
【发布时间】:2014-10-29 21:10:52
【问题描述】:

我一直在尝试构建本地概念验证,以将我们当前的解决方案转移到不同的 URL 结构。我正在将 ASP.NET 与 3 个项目一起使用,这些项目当前已将这些 URL 映射到它们:

mysite.com
mysite.com/api
mysite.com/app

为了设置概念验证,我在 IIS 中使用以下 URL 本地设置了 3 个站点:

mysite.com
api.mysite.com
app.mysite.com

并已将以下条目添加到 HOSTS 文件中:

127.0.0.1 mysite.com
127.0.0.1 app.mysite.com
127.0.0.1 api.mysite.com

目前app.mysite.comapi.mysite.com 对话以执行用户登录,这会在响应中返回一个cookie。问题是 cookie 没有存储在mysite.com 下。对api.mysite.com 的后续请求没有在请求标头中附加 cookie,因此会失败。

我尝试过设置 cookie 的 domain 属性,但没有成功,也没有包含域属性。

请求中返回的cookie示例:

Set-Cookie: MyCookie=somestuff; domain=.mysite.com; expires=Sat, 06-Sep-2014 00:02:04 GMT; path=/; HttpOnly

然而,cookie 从未附加到对api.mysite.com 的任何请求,我也无法在 Chrome、Firefox、IE 等的 cookie 浏览器中看到它...

请注意,我在 web.config 中启用了 CORS 以启用跨域请求。

编辑: 回应欧文的回答。我将进一步澄清我当前的设置。

关于<machineKey>,我创建了一个machineKey,并在web.config 文件中的两个应用程序上使用了相同的值。使用 mysite.com/apimysite.com/app 时,这已经在本地和生产环境中工作了。直到移动到子域时我才遇到这个问题。

这是我创建和附加 cookie 的代码:

        private void EncryptAndAttachCookieToHeaders(FormsAuthenticationTicket ticket)
        {

            string encryptedTicket = FormsAuthentication.Encrypt(ticket);

            HttpCookie newCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
            newCookie.Domain = ".mysite.com";
            newCookie.Expires = DateTime.Now.AddMonths(3);
            newCookie.HttpOnly = true;
            newCookie.Secure = false; 

            System.Web.HttpContext.Current.Response.Cookies.Add(newCookie);

        // For testing purposes
        HttpCookie hc = new HttpCookie("cookie1", "value");
        hc.Domain = ".mysite.com"; 
        hc.Expires = DateTime.Now.AddMonths(3);
        HttpContext.Current.Response.Cookies.Add(hc);

        HttpCookie hd = new HttpCookie("cookie2", "value");
        hd.Domain = ".api.mysite.com"; 
        hd.Expires = DateTime.Now.AddMonths(3);
        HttpContext.Current.Response.Cookies.Add(hd);

在 Fiddler 中查看响应时,所有这些 cookie(真正的一个加上两个测试)都是可见的。然而,对api.mysite.com 的后续请求在请求标头中附加了任何 cookie。既然我已经移动到子域结构,浏览器似乎不想存储 cookie。

【问题讨论】:

    标签: asp.net iis cookies


    【解决方案1】:

    我找到了答案。问题实际上在于 AJAX 请求是如何形成的。我必须添加一个名为withCredentials 的AJAX 属性,以允许浏览器发送跨域cookie。这种方法的一个缺点是 IE 9 和更早版本不支持它....

    来自Setting a cookie on a subdomain from an ajax request 的帖子:

    在 api 上设置允许凭据标头

    Access-Control-Allow-Credentials: true
    

    对请求使用 withCredentials

    $.ajax({
        url: a_cross_domain_url,
        xhrFields: { 
            withCredentials: true 
        }
    });
    

    否则 XMLHttpRequest 将不会发送 cookie,无论 Access-Control-Allow-Credentials 标头如何。

    移除 Access-Control-Allow-Origin 上的通配符

    Access-Control-Allow-Origin: http://www.example.com
    

    通配符* 不起作用。如果设置了withCredentials,浏览器将丢弃响应。

    【讨论】:

      【解决方案2】:

      要进行跨域登录,您首先需要编辑 web.config 中的 <machineKey> 元素。

      默认是这样的

      <machineKey
          validationKey="AutoGenerate,IsolateApps"
          decryptionKey="AutoGenerate,IsolateApps"
          validation="SHA1"
          decryption="Auto" />
      

      通过这些设置,.NET 框架使用自动生成的validationKey 和decrytionKey

      在默认设置下,验证密钥和解密密钥将由 ASP.NET 生成并用于身份验证票证和 cookie,如果您希望多个应用程序共享相同的身份验证票证和 cookie,您只需设置将所有应用程序中的validationKey 和decrytionKey 设置为相同的值

      确保它们在两个应用程序中都相同,例如

      <machineKey
          validationKey="FBFF3D4EFD359FD58AA480E0A63A9C817463A30EF5AFF4E212AD3321C122AECFFEC427C26D24B67296F5EBBB6A3736BF37A5027718E5426B92C9AC606F9AD66F"
          decryptionKey="048F8A9F3D6A7D2E88738B36BEEB85FF0B4E23EEF11976D1C0F6F03B91CCFC37"
          validation="SHA1"
          decryption="AES" />
      

      您可以在此站点上轻松创建一些密钥http://aspnetresources.com/tools/machineKey

      要使身份验证 cookie 在所有其他子域中可见,您需要修改 cookie 的域属性。

      // Call SetAuthCookie method
      FormsAuthentication.SetAuthCookie("Test account", false);
      
      //modify the Domain attribute
      System.Web.HttpCookie TestCookie = 
             System.Web.Security.FormsAuthentication.GetAuthCookie(User.Identity.Name.ToString(), false);
      
      TestCookie.Domain = "mysite.com"; // (Also try ".mysite.com" i'm unsure about this one) the second level domain name
      Response.AppendCookie(TestCookie);
      

      这应该是使跨域 cookie 工作所需的一切

      【讨论】:

      • 感谢您的回答欧文。我已经编辑了我的问题以解决您提出的问题。
      猜你喜欢
      • 2015-12-21
      • 2021-09-11
      • 2017-02-02
      • 1970-01-01
      • 2013-01-05
      • 1970-01-01
      • 1970-01-01
      • 2011-11-27
      • 2015-08-09
      相关资源
      最近更新 更多