Recently, I've been working on an MVC 4 web application project where I needed to implement the "remember me" feature on the website. I found two solutions to this problem, and I'd like to share my solution with all of you.
We are implementing the "remember me" functionality on the login page of our ASP.NET MVC project. The first approach involves using the `FormsAuthentication.SetAuthCookie` function, which utilizes the Forms authentication mode.
We are going to implement a "remember me" functionality on the login page of our ASP.NET MVC project. The first approach to achieve this is by using the `FormsAuthentication.SetAuthCookie` function, which utilizes the Forms authentication mode.
We can also do that by creating cookies but just I want to let you know that
If You want make secure web application then should never store the user’s credentials in a cookie. It is un-secure. ASP.Net MVC already gives this functionality securely with Forms Authentication and ASP Membership Providers if you are using the Membership implementation.
You should take the advantage of that. When creating a default Asp .NET MVC project, Visual will include the basic authentication setup and project structure for us. you can use that setup for implementing the remember me feature.
In this Part, I will Explain to you Following Points:-
public class LoginViewModel
{
[Required]
[Display(Name = "Email")]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
ManageAccount
.csusing RememberMe.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
namespace RememberMe.Controllers
{
public class ManageAccountController : Controller
{
// GET: ManageAccount
public ActionResult Login()
{
return View();
}
// GET: ManageAccount
[HttpPost]
[AllowAnonymous]
public ActionResult Login(LoginViewModel model)
{
DummyDbEntities db = new DummyDbEntities();
string strresponse = string.Empty;
var user = db.Users.Where(a => a.Email == model.Email && a.Password == model.Password).FirstOrDefault();
if (user != null)
{
//user active
if (user.UserStatus == 1)
{
FormsAuthentication.SetAuthCookie(user.Email, model.RememberMe);
return RedirectToAction("UserProfile");
}
else
{
strresponse = "Your Account has not been activated.Please connect to admin";
}
}
else
{
strresponse = "Username or password is incorrect.Please try again!";
}
ViewBag.Message = strresponse;
return View();
}
// GET: ManageAccount/UserProfile
public ActionResult UserProfile()
{
return View();
}
[HttpPost]
public ActionResult Logout()
{
FormsAuthentication.SignOut();
return RedirectToAction("Login");
}
}
}
ManageAccountController.cs manages user login, authentication, and logout operations for the web application.
@using RememberMe.Models
@model LoginViewModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="container body-content">
<div class="row">
<div class="col-md-8">
<section id="loginForm">
@using (Html.BeginForm("Login", "ManageAccount", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<h4>Use a local account to log in.</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
}
</section>
</div>
</div>
<hr />
</div>
@if (@ViewBag.Message != null)
{
<script type="text/javascript">
$(function () {
alert("@ViewBag.Message")
});
</script>
}
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@*@RenderSection("scripts", required: false)*@
</body>
</html>
@using RememberMe.Models
@model LoginViewModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="container body-content">
<div class="row">
<div class="col-md-8">
<div>
@if (Request.IsAuthenticated)
{
<strong>Welcome @Html.Encode(User.Identity.Name)</strong>
using (Html.BeginForm("Logout", "ManageAccount", FormMethod.Post))
{
<a href="javascript:;" onclick="document.forms[0].submit();">Logout</a>
}
}
else
{
<a href="@Url.Action("","")" class="navbar-brand">Login</a>
}
</div>
</div>
</div>
<hr />
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
</body>
</html>
Step:4
set forms in authentication Web.Config
Add below line in web.config
<authentication mode="Forms">
<forms defaultUrl="/ManageAccount/login" loginUrl="/ManageAccount/login" slidingExpiration="true" timeout="2880"></forms>
</authentication>
ASP.NET web application's web.config file related to forms authentication.
<authentication mode="Forms">: attribute specifies the authentication mode used by the application, which in this case is Forms authentication. Forms authentication allows you to authenticate users based on forms they fill out, typically with a username and password.
defaultUrl="/ManageAccount/login": Specifies the default URL to redirect users to after they've been authenticated. In this case, it's set to "/ManageAccount/login", indicating that users will be redirected to the login page if they try to access a restricted area without logging in first.
loginUrl="/ManageAccount/login": the URL of the login page where users are redirected if they need to authenticate before accessing a protected resource. In this example, it's set to "/ManageAccount/login".
slidingExpiration="true": indicates whether to enable sliding expiration for the authentication ticket. When set to true, it means that the timeout period for the authentication ticket is extended each time a request is made within half the timeout period. This helps keep users logged in as long as they are active.
timeout="2880": sets the timeout period for the authentication ticket, measured in minutes. In this case, the timeout is set to 2880 minutes (48 hours), meaning that users will need to reauthenticate after being inactive for that duration.
sets up Forms authentication for the ASP.NET application, specifying various parameters such as default URLs, expiration settings, and the authentication mode.
if below line present in the config file then remove
<remove name="FormsAuthentication" />
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
DNBJD
ASP.NET MVC controller and handles the HTTP POST request for user login.
A standard login action in ASP.NET MVC using Identity framework, which handles user authentication and account lockout features.
Profile page
@using Microsoft.AspNet.Identity
@if (Request.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
@Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right">
<li>
@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
</li>
<li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
</ul>
}
}
else
{
<ul class="nav navbar-nav navbar-right">
<li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
<li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}