web-dev-qa-db-ja.com

ASP.NET MVCで「Remember Me」機能を実装する

ログインフォームに「記憶」機能を実装しようとしています。 WebアプリケーションとしてASP.NET MVCを使用しています。 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 Loginアクションメソッドをトリガーすることであり、ユーザーのログインを処理するPOSTではありません。

私はこれについて完全に間違っていますか?または、RedirectToActionまたは他の方法を使用してPOST Loginメソッドを呼び出すことができる方法がありますか?

22
Kassem

まず、ユーザーの資格情報をCookieに保存しないでください。それは信じられないほど安全ではありません。パスワードは、リクエストごとに渡されるだけでなく、ユーザーのマシンにプレーンテキストで保存されます。

第二に、特にセキュリティが懸念される場合、車輪を再発明しないでください。

ASP.Netは、この機能をForms Authenitcation and Membership Providersで既に安全に提供しています。あなたはそれを調べる必要があります。デフォルトのMVCプロジェクトを作成すると、基本認証のセットアップが含まれます。公式の MVCサイト にはもっとあります。

更新

メンバーシッププロバイダーを実装しなくても、引き続き.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");

  }

}
54
David Glenn