.NET Framework allow you authorization engine based on two layer security: users and roles. Most popular is SQL Membership Provider and it contains methods and properties specific to using SQL as a data store for membership information. But for standard Membership provider you should create separate database. To use users or contacts information from your DB for authentication users with standard .NET form authorization you can create Custom Membership Provider and Custom Role Provider. Today we will create simple Custom Membership Provider and I’ll show how to configure it for using in MVC.
First we need create class inherits from the MembershipProvider class, which provides data store-agnostic methods for storing membership information and checking login info.
Class have ValidateUser function where we can put our logic for user login validating:
public override bool ValidateUser(string username, string password) { if (username.Equals("Shaman", StringComparison.CurrentCultureIgnoreCase) && password.Equals("password")) return true; else return false; }
Of course here you can query DB for checking user info. Then we need configure solution to use created membership provider (web.config file):
<system.web> ... <authentication mode="Forms"> <forms loginUrl="~/Account/LogOn" timeout="2880" /> </authentication> <membership defaultProvider="KitsulaMembershipProviter"> <providers> <clear /> <add name="KitsulaMembershipProviter" type="Kitsula.Security.KitsulaMembershipProviter" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="5" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" /> </providers> </membership> ... </system.web>
We set settings redirect to ~/Account/LogOn page if user is trying open protected page. Let’s create this login page.
Controller:
Model:
/// LogOnModel.cs using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel; namespace Kitsula.Security { public class LogOnModel { [Required] [DisplayName("User name")] public string UserName { get; set; } [Required] [DataType(DataType.Password)] [DisplayName("Password")] public string Password { get; set; } [DisplayName("Remember me?")] public bool RememberMe { get; set; } } }
View:
Back to the controller handle post command from view:
/// AccountController.cs using System; using System.Web.Mvc; using Kitsula.Security; using System.Web.Security; namespace Kitsula.Controllers { public class AccountController : Controller { // // GET: /Account/LogOn public ActionResult LogOn() { return View(); } [HttpPost] public ActionResult LogOn(LogOnModel model, string returnUrl) { if (ModelState.IsValid) { if (new KitsulaMembershipProvider().ValidateUser(model.UserName, model.Password)) { FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); if (!String.IsNullOrEmpty(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } else { ModelState.AddModelError("", "The user name or password provided is incorrect."); } } // If we got this far, something failed, redisplay form return View(model); } } }
Done. We create Custom Membership Provider. Instead of protect folders or files (like it is in Web Forms) in MVC model you can protect any controller by putting [Authorize()] attribute to the controller class definition (in my case I put this attribute for all controllers in Admin area):
using System; using System.Web.Mvc; namespace Kitsula.Areas.Admin.Controllers { [Authorize()] public class HomeController : Controller { // // GET: /Admin/Home/ public ActionResult Index() { return View(); } } }
Let’s test and open default page in Admin area http://localhost/Admin. We should be redirected to login page (as expected):
After login, we will be redirected to protected page:
Sources: