我有一个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标头...
答案 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将在浏览器会话中保留一年。