在iOS Safari上的浏览器会话之间未保存Cookie

时间:2014-07-16 13:08:42

标签: c# ios asp.net-mvc session cookies

我有一个MVC 4网站,用户可以登录,我保存一个cookie及其会话信息,这样他们就不必再次登录了。

public void SetCookie(HttpCookie cookie)
{
    HttpContext.Current.Response.Cookies.Set(cookie);
}

这适用于桌面设备,但是当我在iOS上运行它时,它无法在100%的时间内正常工作。如果我在移动浏览器(Chrome或Safari)中打开至少1页并导航回我的网站,则会找到我的会话cookie,而不必登录。但是,如果我关闭该浏览器的所有窗口,那么下次我导航回我的网站时,找不到会话cookie。我在我的cookie上设置了1年的持续时间/到期时间,因此它没有到期。

到目前为止,我唯一发现的是这是.NET 4.0中的一个错误,并在.NET 4.5中得到修复。我相信我已经运行了.NET 4.5,通过查看我的* .csproj和TargetFrameworkVersion元素:

<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>
    </ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{xxxxxxxxxxxxxxxxxx}</ProjectGuid>
    <ProjectTypeGuids>{xxxxxxxx};{xxxxxxxxxxxxx};{xxxxxxxxxxxxxxxx}</ProjectTypeGuids>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>MyApp</RootNamespace>
    <AssemblyName>MyApp</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <MvcBuildViews>false</MvcBuildViews>
    <UseIISExpress>true</UseIISExpress>
    <IISExpressSSLPort />
    <IISExpressAnonymousAuthentication />
    <IISExpressWindowsAuthentication />
    <IISExpressUseClassicPipelineMode />
  </PropertyGroup>

这是.NET(或MVC)的错误,还是我的编码?我是否需要升级到MVC 5(而不是升级到.NET 4.5的原始建议)?

由于未来几个月我网站的大部分流量都来自移动用户,这真的让我感到烦恼,如果他们每次都必须继续登录,我可能会失去一些(我知道我讨厌必须登录移动设备...)

修改

顺便说一句 - 这是关于同一主题的另一页:Asp.Net Forms Authentication when using iPhone UIWebView

我也试过实现这个并且它也不起作用:

http://www.bloggersworld.com/index.php/asp-net-forms-authentication-iphone-cookies/

以上内容包括Scott Hanselmans建议修复:

http://www.hanselman.com/blog/FormsAuthenticationOnASPNETSitesWithTheGoogleChromeBrowserOnIOS.aspx

这是我的cookie创建代码,以防它有用:

private void CreateAndSetAuthenticationCookie(int loginId, string username)
    {
        HttpCookie cookie = CreateAuthenticationCookie(loginId, username);

        _cookieService.SetCookie(cookie);
    }

    private HttpCookie CreateAuthenticationCookie(int loginId, string username)
    {
        string userData = string.Format("loginId:{0},username:{1}", loginId, username);
        var ticket = new FormsAuthenticationTicket(loginId, username, DateTime.Now, DateTime.Now.AddYears(1), false, userData, FormsAuthentication.FormsCookiePath);
        string encryptedTicket = FormsAuthentication.Encrypt(ticket);

        return new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
    }

我在评论中指出的一件事是,我将“PersistentCookie”设置为假......不确定这是否有所作为,我会做更多的研究。

更新

首先,PersistentCookie现在设置为true,并且没有对行为进行任何更改。

下面的评论之一表明我在从iPhone访问网站时运行Fiddler。经过非常简单的步骤来完成设置后,这就是我发现的内容。

我试过的第一个请求(我相信)实际问题是什么。当我检查第一个请求时,iOS Safari正在发送DNT标头。我不知道那是什么,我查了一下,这是一个“Do Not Track”标题。

接下来,我去检查我的Safari设置以关闭它。猜猜看,它已经关闭了。为什么Safari(iOS)在未设置设置(设置 - &gt; Safari - &gt;不跟踪)时发送DNT标头?此外,位于其下方的Block Cookies设置为“从不”。

在对此感到沮丧之后,我去检查Chrome for iOS以查看是否仍然无效。有用!据我所知,我将关闭所有标签,再次尝试,关闭所有标签,然后终止浏览器,它仍然有效。万岁!

现在,我需要弄清楚为什么iOS Safari会发送DNT标头...

2 个答案:

答案 0 :(得分:23)

这是令人难以置信的尴尬。我发现我的iOS Safari浏览器已经在“私人浏览模式”中使用了一年!

我觉得我的“软件开发人员”职称需要删除一段时间。很抱歉浪费每个人的时间。

答案 1 :(得分:2)

我认为你用持久性cookie回答了你自己的问题。常规cookie在浏览器会话结束时到期(这通常是关闭浏览器)。持久性cookie具有应该被删除的日期,并且可以跨浏览器会话生效。

您的代码应如下所示:

private HttpCookie CreateAuthenticationCookie(int loginId, string username)
{
    string userData = string.Format("loginId:{0},username:{1}", loginId, username);
    var ticket = new FormsAuthenticationTicket(loginId, username, 
                         DateTime.Now, DateTime.Now.AddYears(1), 
                         false, userData, FormsAuthentication.FormsCookiePath);
    string encryptedTicket = FormsAuthentication.Encrypt(ticket);

    return new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket){{
         Expires = DateTime.Now.AddYears(1);
    }};
}

这样,您的Cookie将在浏览器会话中保留一年。