在 ASP.NET MVC 中实现“记住我”功能

Posted

技术标签:

【中文标题】在 ASP.NET MVC 中实现“记住我”功能【英文标题】:Implementing "Remember Me" Feature in ASP.NET MVC 【发布时间】:2011-08-02 22:49:02 【问题描述】:

我正在尝试在我的登录表单中实现“记住我”功能。我使用 ASP.NET MVC 作为我的 Web 应用程序。我设法让 cookie 工作,但我未能自动登录用户,以防他/她之前检查了记住我复选框。我知道问题是什么,但我不知道如何解决它。

在我的 HomeController 中,我有以下内容:

private LoginViewModel CheckLoginCookie()

    if (!string.IsNullOrEmpty(_appCookies.Email) && !string.IsNullOrEmpty(_appCookies.Password))
    
        var login = new LoginViewModel
                        
                            Email = _appCookies.Email,
                            Password = _appCookies.Password
                        ;

        return login;
    
    return null;



public ActionResult Index()

    var login = CheckLoginCookie();
    if (login != null)
        return RedirectToAction("Login", "User", login);

    var viewModel = new HomeIndexViewModel
                        
                            IntroText =
                                "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
                            LastMinuteDeals = new List<ItemsIndexViewModel>(),
                            TrustedDeals = new List<ItemsIndexViewModel>()
                        ;
    return View(viewModel);

在我的 UserController 中,我有 Login 操作方法:

public ActionResult Login()

    return PartialView(new LoginViewModel());


[HttpPost]
public ActionResult Login(LoginViewModel dto)

    bool flag = false;
    if (ModelState.IsValid)
    
        if (_userService.AuthenticateUser(dto.Email, dto.Password, false)) 
            var user = _userService.GetUserByEmail(dto.Email);
            var uSession = new UserSession
            
                ID = user.Id,
                Nickname = user.Nickname
            ;
            SessionManager.RegisterSession(SessionKeys.User, uSession);
            flag = true;

            if(dto.RememberMe)
            
                _appCookies.Email = dto.Email;
                _appCookies.Password = dto.Password;
            
        
    
    if (flag)
        return RedirectToAction("Index", "Home");
    else
    
        ViewData.Add("InvalidLogin", "The login info you provided were incorrect.");
        return View(dto);
    

所以基本上,我想我会做的是从家庭控制器上的索引操作结果重定向用户,以防有登录 cookie。但问题是 RedirectToAction 将触发 GET 登录操作方法,而不是负责登录用户的 POST。

我在这件事上完全错了吗?或者有什么方法我可以使用 RedirectToAction 或任何其他方式调用 POST 登录方法?

【问题讨论】:

【参考方案1】:

首先,您不应该将用户的凭据存储在 cookie 中。这是令人难以置信的不安全。密码将随每个请求一起传递,并以纯文本形式存储在用户的机器上。

第二,不要重新发明***,尤其是在安全方面,你永远不会做对。

ASP.Net 已经通过表单身份验证和成员资格提供程序安全地提供了此功能。你应该看看那个。创建默认 MVC 项目将包括基本身份验证设置。官方MVC site还有更多。

更新

您仍然可以在不实现成员资格提供程序的情况下使用 .NET 表单身份验证。在基本层面上,它会像这样工作。

您在 web.config 中启用表单身份验证

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

您使用[Authorize] 属性装饰您想要保护的操作或控制器。

[Authorize]
public ViewResult Index() 
  //you action logic here

然后创建一个基本的登录动作

[HttpPost]
public ActionResult Login(LoginViewModel dto) 

  //you authorisation logic here
  if (userAutherised) 
    //create the authentication ticket
    var authTicket = new FormsAuthenticationTicket(
      1,
      userId,  //user id
      DateTime.Now,
      DateTime.Now.AddMinutes(20),  // expiry
      rememberMe,  //true to remember
      "", //roles 
      "/"
    );

    //encrypt the ticket and add it to a cookie
    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,   FormsAuthentication.Encrypt(authTicket));
    Response.Cookies.Add(cookie);

    return RedirectToAction("Index");

  


【讨论】:

+1 特别是用于创建默认 mvc 项目。如果我有任何需要登录功能的项目,我会创建一个新的 mvc 互联网应用程序,然后从那里更改代码。 @David Glenn:我完全理解,但是当我第一次开始从事这个项目并决定不使用 ASP.NET Membership API 时,我已经经历过这个,因为它笨重、丑陋并且不适合我的需要。另外,我使用 EF Code First 作为我的 ORM,所以我找不到使用 Membership API 并使用代码生成数据库的方法。无论如何,如果我不打算将凭据存储在 cookie 中,我该如何实现“记住我”功能? @Rory McCrossan:请不要将用户 ID 存储在 cookie 中。用户只需单击几下即可编辑该 cookie 并以其他用户身份登录。 我必须添加它才能正常工作: if (authTicket.IsPersistent) cookie.Expires = authTicket.Expiration;就在将 cookie 添加到响应之前 可以,有人告诉我再次打开网站时如何检查cookie吗?

以上是关于在 ASP.NET MVC 中实现“记住我”功能的主要内容,如果未能解决你的问题,请参考以下文章

关于在 asp.net mvc 中实现忘记密码功能的一些问题

csharp 在asp.net mvc中实现工作单元模式

在 ASP.NET MVC 2 中实现 DropDownList 的最佳方式?

如何在 ASP.NET MVC 5 和 WEB API 2 中实现 oauth2 服务器 [关闭]

在 ASP.NET MVC 中实现配置文件提供程序

如何在 ASP.Net MVC 中实现视频文件流式传输?