A web application needs some form of user authentication. You will be creating one that uses Couchbase to store the user records. You would most likely back this data up to long-term persistent storage to avoid any data loss. Couchbase does write to disk in the case of memory pressure, and it can be considered persistent if the all of the machines are running perfectly. You can also ensure that there are replicas in the case of single or multiple machine failures. For illustrative purposes, we'll just store the user records into Couchbase.
Edit HomeController.cs and add the methods in Listing 8 after the
Create() actions.
Listing 8, Login actions
/// <summary> /// GET: /Home/Login /// </summary> /// <returns></returns> public ActionResult Login() { return View(); } /// <summary> /// POST: /Home/Login /// </summary> /// <param name="collection"></param> /// <returns></returns> [HttpPost] public ActionResult Login(FormCollection collection) { var client = MvcApplication.CouchbaseClient; var sessionToken = Guid.NewGuid(); var cookie = new HttpCookie("COUCHBASE_SESSION", sessionToken.ToString()); ControllerContext.HttpContext.Response.Cookies.Add(cookie); var encodedPassword = EncodePassword(collection["Password"]); // Design a key that the user will be able to retrieve again, if and only if // they remember what their password is. This is likely not the only way to // do something like this. String userKey = string.Format("User-{0}-{1}{2}", collection["UserName"], AppSecret, encodedPassword); client.Store(StoreMode.Set, sessionToken.ToString() + AppSecret, userKey, TimeSpan.FromMinutes(SessionTimeoutMinutes)); // Try to retrieve the user data from the database. If it returns null, // the user has logged in incorrectly var userId = client.Get<Guid>(userKey); var user = client.Get<User>(userId.ToString()); // If user is null the login failed otherwise show the Index page. return RedirectToAction(user == null ? "Login" : "Index"); }
The first method returns the login form, and the second method
responds to the POST when the user presses the submit button. The
user's entered UserName and Password are taken from the collection
object. Here, we format the userKey in the same
way, and store the userKey into the database by
using the sessionToken combined with the
AppSecret. This is to help you learn about
Couchbase, not to be taught a lesson about security. This is not
secure at all, in fact. More thought would have to be made on how
to provide even a small amount of security to keep unauthorized
people out.
Once the keys are correct, if the database contains a record for
the userKey, the user's userId will be found,
and from that the stored User record will be found. If the code
finds a User, the browser will be redirected to the Index action,
otherwise back to the Login action it goes.
Next add a new view to the Views/Home folder named Login with content from Listing 9.
Listing 9, Login.cshtml
@{ ViewBag.Title = "Login"; } <h2>Login</h2> @using (Html.BeginForm()) { Html.ValidationSummary(true); <fieldset> <legend>Please log in to the system:</legend> <p> UserName: <input type="text" name="UserName" /> </p> <p> Password: <input type="password" name="Password" /> </p> <p> Don't have an account? @Html.ActionLink("Create one...","Create") </p> <p> <input type="submit" value="Log In" /> </p> </fieldset> }
Notice here, that an action link has been set up in the login page to create a new user account if you haven't already created one. This executes the create action from the previous stage.
Next you will likely want to be able to log out of the application
to add other users for testing. Add the Logout
action in Listing 10 after the Login actions in HomeController.cs.
Listing 10, Logout action
/// <summary> /// GET /Home/Logout /// </summary> /// <returns></returns> public ActionResult Logout() { var client = MvcApplication.CouchbaseClient; var cookie = ControllerContext.HttpContext .Request.Cookies["COUCHBASE_SESSION"]; if (cookie != null) { var sessionToken = cookie.Value; client.Remove(sessionToken + AppSecret); } return RedirectToAction("Login"); }
The Logout action gets the COUCHBASE_SESSION
cookie, reads the sessionToken and removes that
token from the database. Then it redirects the user's browser to
the Login action. Once the session token is removed, the cookie is
effectively invalid.
Finally you need to add the logout link to the bottom of the Index view:
<p>@Html.ActionLink("Logout...","Logout")</p>At this point, you should be able to start using the application to create user accounts, and log in and out of these accounts given the username and password. However, the flow of the application would be enhanced by the addition of an authentication check. You will add this in the next stage.