【问题标题】:Multiple sub-domain FormsAuthentication not working, using Web API MVC 4多个子域 FormsAuthentication 不起作用,使用 Web API MVC 4
【发布时间】:2023-03-10 18:14:02
【问题描述】:

我正在做一个需要网站和移动应用程序的项目,几乎具有相同的功能。 因此,为此我正在使用 Asp.net Web API 构建 API,该 API 也将用于网站和移动应用程序。

API 地址为:api.domain.com 网址是:testing.domain.com

问题:

现在在 api.domain.com,我允许用户登录,FormsAuthenticationCookies 一起使用。

当用户通过身份验证时,它会获得 200 Http Satus 以及 Set-Cookie 标头,其中还提到了允许的域。

这是请求和响应:

**Request**

Request URL:http://api.domain.com/account/login
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:139
Content-Type:application/x-www-form-urlencoded
Host:api.domain.com
Origin:http://testing.domain.com
Referer:http://testing.domain.com/Login.aspx?ReturnUrl=%2fteacherpanel
User-Agent:Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1
Form Dataview URL encoded
__VIEWSTATE:/wEPDwUKMTY1NDU2MTA1MmRkmpJ4YQ4kteUpklwLOmcHppPgq/RHqfw7tilyk8pJp0Y=
UserName:ishan
Password:pass





**Response**

Access-Control-Allow-Headers:Content-Type
Access-Control-Allow-Methods:PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Origin:*
Cache-Control:no-cache
Content-Length:0
Date:Sat, 22 Sep 2012 10:23:38 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/7.5
Set-Cookie:.Teacher=A3BD94D26CF733F6F223198ADE40D87C76D8ECC663D7CEDD6E3FF18B0ED23032F6089EF24141E0B65F3F29503A3AC1670C92B9CE4EF7D986974ABE61AB5F0C837245D1A30A8D8E8E058F9AFDD89281CBAB9A3EB98B4A320E689718AF9E76E4911506EBA7FD4244336D8409CFB6D77B179764726B550AB0FFF7A6508658615A57; domain=domain.com, .domain.com; path=/; HttpOnly
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

现在根据响应,浏览器应该将此 cookie 发送到服务器,每次请求到此域 domain.com 或其任何 子域

但这并没有发生,今天早上它对我有用,但我不知道我发布后发生了什么。

另外,这里是我用来设置 cookie 并检查用户是否登录的代码。

此处为登录用户,此检查在 API 中执行,位于 api.domain.com。

[AllowAnonymous]
        [HttpPost]
        public HttpResponseMessage Login(LoginModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                Teacher t;
                if (Teacher.Login(model.UserName,model.Password,out t))
                {
                   // Roles.AddUserToRole(t.ID.ToString(), "teacher");

                    FormsAuthentication.SetAuthCookie(t.ID.ToString(), model.RememberMe);






                    FormsAuthenticationTicket ft = new FormsAuthenticationTicket(
                     1,                                   // version
                     t.ID.ToString(),   // get username  from the form
                     DateTime.Now,                        // issue time is now
                     DateTime.Now.AddMinutes(30),         // expires in 10 minutes
                     true,      // cookie is not persistent
                     "teacher"                              // role assignment is stored
                        // in userData
                     );

                    string enTicket = FormsAuthentication.Encrypt(ft);


                    HttpResponseMessage res = Request.CreateResponse(HttpStatusCode.OK);


                    System.Net.Http.Headers.CookieHeaderValue cokie = new System.Net.Http.Headers.CookieHeaderValue(FormsAuthentication.FormsCookieName, enTicket);
                    cokie.Domain = "domain.com  .domain.com";
                    IEnumerable<System.Net.Http.Headers.CookieHeaderValue> cookies = new System.Net.Http.Headers.CookieHeaderValue[] { cokie };

                    res.Headers.AddCookies(cookies);


                    return res;

                }
                return Request.CreateResponse(HttpStatusCode.Unauthorized);
            }

            // If we got this far, something failed, redisplay form
            return Request.CreateResponse(HttpStatusCode.Unauthorized);
        }

现在在 testing.domain.com,只需在 web.config 中根据其角色检查用户的身份验证。

<location path="TeacherPanel">
    <system.web>
      <authorization>
        <allow roles="teacher" />
        <deny users="?" />
      </authorization>
    </system.web>
  </location>

这些是我在研究这个问题时发现要检查的细节。随意提出任何建议,每条线索都会有所帮助。

testing.domain.com 的 Web 配置中的身份验证部分

 <authentication mode="Forms">
      <forms name=".Teacher" loginUrl="Login.aspx" protection="All" path="/" timeout="30" domain=".domain.com" />
    </authentication>

api.domain.com 的网络配置中的身份验证部分

 <authentication mode="Forms">
  <forms  name=".Teacher"
    cookieless="UseCookies"
    requireSSL="false"
     domain=".domain.com"
     />
</authentication>

添加机器密钥并为 Cookie 添加过期时间后

通过浏览器发布请求以进行身份​​验证:

POST /account/login HTTP/1.1
Host: api.domain.com
Connection: keep-alive
Content-Length: 123
Origin: http://testing.domain.com
User-Agent: Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1
Content-Type: application/x-www-form-urlencoded
Accept: */*
Referer: http://testing.domain.com/TeacherLogin.aspx?ReturnUrl=%2fteacherpanel
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

__VIEWSTATE:/wEPDwUKMTY1NDU2MTA1MmRkCjMwS9YdCRDD3Qsd4GYnLj+tGGg=
UserName:username
Password:pass

服务器发送的响应:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/7.5
Set-Cookie: .Teacher=9C8FD43FABDC1817D21272361CBF798BB64C364DECC62E2F5F666D1B2A248076C67737D89B03F515D4D81524345584B11E206B2DDEAD5AA846A15BC17B32D86DF1C95A2943766AB5955C99A8DD0D5984089131838E158A90241B60D40A2D928086486E2BA3DDE95814E7FA303845FBDE235D69F54B6891852A09A80F7465FF8C59957A4D; expires=Wed, 26 Sep 2012 10:02:46 GMT; max-age=432000; domain=.domain.com; path=/; secure; httponly
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
Date: Tue, 25 Sep 2012 10:02:46 GMT
Content-Length: 0

下一个 Get Request 发送到 testing.domain.com 进行测试(由于浏览器未将 cookie 发送回服务器而失败):

GET / HTTP/1.1
Host: testing.domain.com
Connection: keep-alive
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1
Accept: */*
Referer: http://testing.domain.com/TeacherLogin.aspx?ReturnUrl=%2fteacherpanel
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

你猜为什么浏览器不发回 Cookie?

【问题讨论】:

  • 您能否也发布您的 web.config 的 部分? API 和测试都有 web.config 吗?如果是这样,您是否确保机器密钥匹配?
  • 刚刚添加了 部分,但不确定机器密钥在哪里找到以及在哪里插入?
  • 添加了机器密钥以在下面回答
  • 检查您没有正在更改您的值的 web.config 调试转换文件。

标签: asp.net cookies forms-authentication asp.net-web-api


【解决方案1】:

这里可能会发生两件事:

  1. 如果您在 API 和测试 web.config 中都没有 machinekey,那么您可能正在使用从 .Net Framework machine.config 或 web.config 继承的设置。这将为每个应用程序生成不同的密钥,因此在一个应用程序中发布的 cookie 不能被另一个应用程序解密。您应该将相同的machinekey section 添加到每个 web.config。您可以使用众多在线生成器之一,例如this one

  2. 另一个问题是尝试将多个域放在单个 cookie 中。更改此行:

    cokie.Domain = "domain.com .domain.com";

到这里:

cokie.Domain = ".domain.com";

实际上,查看您的部分,您甚至可能不需要这一行,因为它们都设置为在 .domain.com 发出 cookie

编辑:还检查您的 web.config 的 httpCookies section 以控制是否在设置了安全标志的情况下发送 cookie。例如,在开发环境中您想关闭安全标志:

<httpCookies httpOnlyCookies="true" requireSSL="false" />

还有forms tag requireSSL property,但我认为这不适用于您的情况,因为您是手动发出 cookie。

【讨论】:

  • 刚刚做了机器密钥技巧,但没有工作......问题是......一旦浏览器接收到Cookie,它应该必须发送下一个请求,但这里只是不发送它们。似乎缺少某些东西正在阻止浏览器将 Cookie 与下一个请求一起发回。
  • 原始问题有请求/响应,但是您可以在代码/配置更改后发布它现在的样子吗?也是原始响应之后的下一个请求(不发送 cookie 的那个)?
  • 刚刚接近解决方案,问题是cookie的'expire'字段没有设置,你知道为什么服务器没有发送设置过期时间的cookie吗?它是一个 IIS7。
  • cookie 好像有过期时间。但是,我看到在 cookie 上设置了安全标志,但后续请求只是 HTTP。这可能是没有发送 cookie 的原因。
  • 我只是添加了“安全”作为实验,之后我将其删除,但它在这两种方式中都不起作用。我正在研究,在某处我发现了一个线索,表明这个问题可能是因为“Cache-Control”标头,当我将此响应与我们在普通网站中使用 FormsAuthentication 时做出的响应进行比较时。普通网站有 Cache-Control:private, no-cache="set-cookie" 。但这里是缓存控制:无缓存,对我来说似乎有问题。你怎么看,你对“Cache-Control” Header有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 2015-04-15
相关资源
最近更新 更多