清除缓存后,set-cookie无法用于IE11/10

Pie*_*rcy 7 asp.net authentication cookies forms-authentication asp.net-web-api

我目前遇到的问题是,清除缓存/ cookie后,IE10和IE11将不再设置cookie.请求和响应看起来几乎相同但在清除缓存之后,即使看起来设置正确,cookie也永远不会被传递.

下面是我的登录方法如何流动:

 1. VerifyLogin()    -> Fail: Go To Login page
                     -> Pass: Call rest of the AJAX Methods // Enter Login Credentials and submit
 2. Authentication() -> Fail: Prompt the user
                     -> Pass: set forms auth cookie and navigate back to original page, where it will call VerifyLogin() again
Run Code Online (Sandbox Code Playgroud)

一旦Authentication()通过,它们应该毫无问题地通过VerifyLogin()并继续使用该产品.所有调用现在都会传递表单身份验证cookie.

在我看到它失败的实例中,Authentication()调用传递并获得200 OK(并且具有set-cookie响应头)但是,VerifyLogin()然后失败,因为它没有传递cookie.

我真的很难再现这个,但到目前为止我的复制步骤如下.这是从没有运行IE的实例开始的.我不是100%确定这是我的客户遇到的完全相同的问题,但它似乎揭示了他们所看到的同样问题.

  1. 启动IE
  2. 浏览到站点的索引页面并退回登录(验证失败)
  3. 使用凭据登录,Authentication()返回200 OK并具有set-cookie响应头.然后它会导航并调用通过的VerifyLogin().cookie在请求中发送,并且全部成功.后续调用全部工作.
  4. 清除我的缓存和cookie
  5. 浏览到站点的索引页面并退回登录(验证失败,因为它应该)
  6. 使用凭据登录,Authentication()返回200 OK并具有set-cookie响应头.然后它会导航并在此时调用VerifyLogin()失败.即使先前在Authentication()的响应中设置了cookie,也不会在请求中传递cookie.如果我关闭并重新打开IE,它将再次工作.

所以,就像第二次set-cookie响应一样,没有设置cookie.

首先,Heres我web.config的相关部分以及我如何设置表单cookie.

web.config中:

 <authentication mode="Forms">
      <forms enableCrossAppRedirects="true" name="Gator.Express.Auth" timeout="2880" />
    </authentication>
Run Code Online (Sandbox Code Playgroud)

setAuthenticationCookie方法:

 public void SetAuthenticationCookie(string userName, CookieData cookieData)
        {
            //In order to pickup the settings from config, we create a default cookie and use its values to create a 
            //new one.
            var cookie = FormsAuthentication.GetAuthCookie(userName, true);
            var ticket = FormsAuthentication.Decrypt(cookie.Value);

            if (ticket == null)
                throw new Exception("Error setting authorisation cookie. Decryption of default cookie failed.");

            var jsonToken = JsonConvert.SerializeObject(cookieData);

            var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,
                ticket.IsPersistent, jsonToken, ticket.CookiePath);
            var encTicket = FormsAuthentication.Encrypt(newTicket);

            cookie.Value = encTicket;

            HttpContext.Current.Response.Cookies.Add(cookie);
        }
Run Code Online (Sandbox Code Playgroud)

现在,这里是请求和响应的顺序.

工作认证请求

POST http://localhost:55733/api/Authentication HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:61496/Login.html
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 35
DNT: 1
Host: localhost:55733
Pragma: no-cache

Username=michaelGator&Password=XXXX
Run Code Online (Sandbox Code Playgroud)

#工作认证响应

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
Set-Cookie: Gator.Express.Auth=01020FCCF4658183D208FE0F4CC8BA1385D208000C6D00690063006800610065006C004700610074006F00720000012F00FF; path=/; HttpOnly
Set-Cookie: Gator.Express.Auth=0102054E17668183D208FE05CEEABA1385D208010C6D00690063006800610065006C004700610074006F007200377B002200530073006F004100630063006F0075006E0074004900640022003A002200300030003000300030003000300030002D0030003000300030002D0030003000300030002D0030003000300030002D0030003000300030003000300030003000300030003000300022007D00012F00FF; expires=Sun, 05-Jul-2015 08:28:39 GMT; path=/; HttpOnly
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcQXV0aGVudGljYXRpb24=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:28:39 GMT
Content-Length: 14

"michaelGator"
Run Code Online (Sandbox Code Playgroud)

#Working VerifyLogin Request

GET http://localhost:55733/api/VerifyLogin HTTP/1.1
Referer: http://localhost:61496/
Accept: */*
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
DNT: 1
Host: localhost:55733
Cookie: Gator.Express.Auth=0102054E17668183D208FE05CEEABA1385D208010C6D00690063006800610065006C004700610074006F007200377B002200530073006F004100630063006F0075006E0074004900640022003A002200300030003000300030003000300030002D0030003000300030002D0030003000300030002D0030003000300030002D0030003000300030003000300030003000300030003000300022007D00012F00FF
Run Code Online (Sandbox Code Playgroud)

#Ropeal VerifyLogin响应

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcVmVyaWZ5TG9naW4=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:28:39 GMT
Content-Length: 0
Run Code Online (Sandbox Code Playgroud)

下面是非工作的请求和响应集.请注意,Authentication方法返回200 OK和set-cookie命令,但在下一次验证登录调用中,coookie消失了.

#Authentication请求 - 返回它应该但是部分非工作请求

POST http://localhost:55733/api/Authentication HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:61496/Login.html
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 35
DNT: 1
Host: localhost:55733
Pragma: no-cache

Username=michaelGator&Password=XXXX
Run Code Online (Sandbox Code Playgroud)

#Authentication Response-返回它应该但是部分非工作请求

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
Set-Cookie: Gator.Express.Auth=01022054EB9B8183D208FE20D4BEF01385D208000C6D00690063006800610065006C004700610074006F00720000012F00FF; path=/; HttpOnly
Set-Cookie: Gator.Express.Auth=01028447109C8183D208FE84C7E3F01385D208010C6D00690063006800610065006C004700610074006F007200377B002200530073006F004100630063006F0075006E0074004900640022003A002200300030003000300030003000300030002D0030003000300030002D0030003000300030002D0030003000300030002D0030003000300030003000300030003000300030003000300022007D00012F00FF; expires=Sun, 05-Jul-2015 08:30:10 GMT; path=/; HttpOnly
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcQXV0aGVudGljYXRpb24=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:30:10 GMT
Content-Length: 14

"michaelGator"
Run Code Online (Sandbox Code Playgroud)

#Non-Working VerifyLogin Request - 注意,没有cookie通过

GET http://localhost:55733/api/VerifyLogin HTTP/1.1
Referer: http://localhost:61496/
Accept: */*
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
DNT: 1
Host: localhost:55733
Run Code Online (Sandbox Code Playgroud)

#Non-Working VerifyLogin响应 - 由于没有传递Forms Cookie而失败

HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcVmVyaWZ5TG9naW4=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:30:10 GMT
Content-Length: 71

{"$id":"1","Message":"Authorization has been denied for this request."}
Run Code Online (Sandbox Code Playgroud)

有人对此有任何想法吗?

Kei*_*ith 2

您似乎获得了两个身份验证 cookie,这表明您的实现与 ASP.Net 尝试为您自动化的某些内容发生冲突。

有一个FormsAuthentication.SetAuthCookie创建并设置cookie的方法,我认为这已经应用了,所以:

  1. FormsAuthentication.SetAuthCookie获取 cookie(已在同一响应中设置)。
  2. 你的SetAuthenticationCookie火。
  3. 这会调用FormsAuthentication.GetAuthCookie并处理(将 JSON 序列化数据嵌入到新的 cookie 中)原始数据。
  4. 您调用HttpContext.Current.Response.Cookies.Add创建第二个 cookie。
  5. 两个 cookie 都以相同的名称在标头中传递

您还没有清除原始 cookie,.Net 不知道如何处理您处理过的 cookie。

我认为你有两个选择:

  1. 将 JSON 数据拆分为具有不同名称的完全独立的 cookie。
  2. 从头开始创建您自己的 cookie,不要使用任何 .Net 的FormsAuthentication方法。

我个人倾向于前者,因为它是最简单、最快的实现方式。

也许还值得尝试 cookie 名称 - 我不确定所有浏览器都支持 cookie 名称中的句点,但它们都区分大小写。

最后还有一些值得检查的事情 -在 .Net 中设置 cookie 的路径几乎不值得,因为 IIS 将 URL 视为不区分大小写,但浏览器都将 cookie 名称视为区分大小写。