ASP.NET MVC 记住我

13

在搜索了很多后,我没有得到任何答案,最终不得不求助于你。下面我将详细解释我的问题。由于篇幅过长,请不要放弃阅读。我已用简单易懂的语言解释了我的问题。

我一直在开发一个asp.net mvc项目。 我正在使用标准的ASP.NET角色和成员资格。 一切正常工作,但记住我功能根本不起作用。 我列出了所有的工作细节。希望大家能够帮助我解决这个问题。

我只需要这个:

我需要用户登录Web应用程序。在登录时,他们可以选择记住我或不记住我。 如果用户登录并选择记住我,那么我希望浏览器能够记住他们很长一段时间,比如至少一年或者更长时间。就像www.dotnetspider.com、www.codeproject.com、www.daniweb.com和许多其他网站一样。 如果用户不选择记住我,则浏览器应该允许访问网站20-30分钟左右,之后他们的会话应该过期。当用户登录并关闭浏览器而没有注销时,他们的会话也应该过期。

注意:我已经成功地实现了上述功能,而没有使用标准的asp.net角色和成员资格,而是创建了自己的用户表来进行身份验证,将cookie和会话设置在我的其他项目中。但是对于这个项目,我们从一开始就使用了标准的asp.net角色和成员资格。我们认为它会起作用,但在测试时却没有起作用。现在我们不能用标准的asp.net角色和成员资格替换现有的功能,而是要使用我的自定义用户表及其所有内容,你明白我的意思吧。
可能是标准的asp.net角色和成员资格功能出现了某种错误,或者我对标准的asp.net角色和成员资格概念有误。我已经阐述了我想要的内容。我认为这非常简单和合理。
我做了什么
  1. 带有用户名、密码和记住我字段的登录表单。

  2. 我的web.config中的设置:

    <authentication mode="Forms">
    <forms loginUrl="~/Account/LogOn" timeout="2880"/>
    </authentication>

  3. 在我的控制器操作中,我有这个:

    FormsAuth.SignIn(userName, rememberMe);

    public void SignIn(string userName, bool createPersistentCookie) { FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); }

现在的问题如下:

在上面的部分中,我已经说明了"I simply need this"。用户可以成功登录系统。他们的会话存在于web.config中指定的超时值所规定的时间内。我还提供了我的web.config示例。在我的示例中,如果我将超时设置为5分钟,则用户会话在5分钟后过期,这很好。但是,如果用户关闭浏览器并重新打开浏览器,则在“超时”未过期之前,用户仍然可以进入网站而无需登录。超时值的滑动过期也正常工作。现在,如果用户勾选了“记住我”,则用户会话仍然在5分钟后过期。这不是好的行为,对吧?我的意思是说,如果用户勾选了“记住我”,那么他应该被记住很长时间,直到他退出系统或用户手动从浏览器中删除所有cookie。如果用户没有勾选“记住我”,则他的会话应在web.config中指定的超时期限后过期,同时如果用户关闭浏览器,则会话也会过期。问题在于,如果用户关闭浏览器并重新打开它,则仍然可以进入网站而无需登录。

我在互联网上搜索了很多关于这个主题的内容,但是没有找到解决方案。在Scott Gu先生关于完全相同主题的博客文章(http://weblogs.asp.net/scottgu/archive/2005/11/08/430011.aspx)中,用户在评论中抱怨了同样的问题,但是Scott先生并没有给出简单的解决方案。

我在以下地方阅读到了相关信息: http://weblogs.asp.net/scottgu/archive/2005/11/08/430011.aspx 链接

我猜这是很多用户都面临的问题,正如Scott Gu先生在博客文章中所提到的。

非常感谢您的帮助。 提前致谢。


1
你说得对。你的问题太长了。你应该缩短它。 - Dave Van den Eynde
顺便说一句,这是Scott Guthrie先生,也被称为The Gu。 - Dave Van den Eynde
3
一点也不久。没有必要费劲周折才能理解问题。 :) - Arnis Lapsa
5个回答

26

当RememberMe选项被选中时,您希望拥有不同的超时时间,而未选中时则不同。不幸的是,SetAuthCookie方法不允许您手动设置过期时间,所以您需要自己完成。

问题在于如何实现?

ASP.NET MVC使用System.Web.Security的FormsAuthentication类来完成这个任务,因为如果您还想支持配置设置和无cookie浏览和SSL,那么这并不容易,但我认为如果您简单地执行以下操作:

int timeout = rememberMe ? 525600 : 30; // Timeout in minutes, 525600 = 365 days.
var ticket = new FormsAuthenticationTicket(userName, rememberMe, timeout);
string encrypted = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrypted);
cookie.Expires = System.DateTime.Now.AddMinutes(timeout);// Not my line
cookie.HttpOnly = true; // cookie not available in javascript.
Response.Cookies.Add(cookie);

...你将会得到一个基本版本,足以满足你的需求。

注意:我没有测试过这段代码。


Dave,你的解决方案对我有用。但仅仅这样做是不够的。我必须添加一行代码来使它至少记住一年。我已经写下了以下内容。 - NCCSBIM071
如果有人发现无法运行,请确保进程未使用登录控件的重定向URL,您可以在方法的末尾添加Response.Redirect(“./”)来防止默认行为(覆盖web.config中的超时时间)。 - DavidG

4

凯文和戴夫,你们太棒了。

戴夫,除了你的代码,我还需要添加一行来使它正常工作。我的意思是让它至少记住一年。除了你的代码,我不得不给cookie.Expires赋值以使它正常工作。如果没有设置cookie.Expires这一行,则在计算机重新启动时,即在会话结束时,cookie将丢失。我在FireFox中注意到了这一点。我仔细查看了cookie的详细信息,发现:如果未设置cookie.Expires,则Firefox中“Expires:”属性的值为“At the end of the session”,但如果设置了cookie.Expires,则Firefox中“Expires:”属性的值为cookie.Expires值所设置的日期时间。

以下是代码:

int timeout = createPersistentCookie ? 525600 : 2; // Timeout in minutes,525600 = 365 days
var ticket = new FormsAuthenticationTicket(userName,createPersistentCookie,timeout);            
string encrypted = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrypted);
cookie.Expires = System.DateTime.Now.AddMinutes(timeout);//My Line
HttpContext.Current.Response.Cookies.Add(cookie);

谢谢大家,这真的是一个很好的解决方案。

4

针对可能遇到的在共享环境中使用会员身份验证票据的问题,这里有一个快速提示。我在Godaddy上运行了一个MVC网站,并且在记住我方面遇到了麻烦。以下是解决方法:

<system.web>
<machineKey
  validationKey="4C6404A3B305CD6E8CFEAC258F042FB95E45E9C3C2CEC3AAB838996CFBE661E41DF1A1BAC75B9B45E02147612FD9B71CA74DDA50B0D0D6ED11F0BB8E31048953"
  decryptionKey="BC471CF17A97B08A9DF85C7B502AD95680E3BE4418FD9C6CEA57E7F97ED64291"
  validation="SHA1" decryption="AES"
/>

感谢:http://www.geekfreeq.com/aspnet-remember-me-option-forms-authentication-not-working/

那个链接现在显然已经恢复了。 - ventaur
3
您可以在这里创建这些设置:http://aspnetresources.com/tools/machineKey - Gluip

1

这不是问题,这是一个特性 :)

用户的会话尚未过期,因此即使他们关闭并重新打开浏览器,Cookie 仍然有效。

正是 Cookie 的过期使用户的会话失效。


谢谢Kervin,你是正确的。这解决了我的一个疑惑。 - NCCSBIM071

0

我已经实现了同样的功能,当我在Mozila中测试时,它可以正常工作,但在所有电脑的IE8中却无法工作,我也已经更新了IE中接受cookie的设置,但仍然无法工作。

Internet Explorer 8.x

  1. 点击工具菜单。
  2. 在菜单中选择Internet选项 - 将打开一个新窗口。
  3. 在窗口顶部附近点击隐私选项卡。
  4. 点击窗口的默认按钮。
  5. 将滑块移动到低于中高级别的任一级别上(包括中、低、接受所有Cookie)。
  6. 通过单击“确定”保存更改。
  7. 现在您应该能够将商品添加到购物车中了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接