ASP.NET MVC 2 and MongoDb Part 3 – Custom membershipprovider

Out of the box you can easily implement a user management system in a ASP.NET MVC (2) application with very little effort. You can use the SqlMembershipProvider which will create a database for you with tables for maintaining users and their roles. But what if you don’t use SQL as a backend but Mongo instead?
Then you need to implement your own custom membership provider. Here are the steps to do just that.

NB: This is just to get you started! It’s not a very tightly secured authentication system, so don’t use this in production. In production you’ll probably want to use SSL and encrypted passwords.

In ASP.NET MVC it is possible to secure controller actions, like this:

[csharp]
[RequiresAuthentication]
public ActionResult Index()
{
var session = new MongoSession();
{
var userlist = session.users.AsEnumerable();
return View(userlist);
}
}
[/csharp]

By adding the RequiresAuthentication attribute above the controller method ‘Index’, the /User/Index page is secured.

To accomplish this, we need to take the following steps:

  • Add the authentication attribute class
  • Add a membership class which implements the MembershipProvider interface
  • Add a Controller and a View
  • Modify web.config

Let’s start with the RequiresAuthenticationAttribute class, which inherits from the ActionFilterAttribute:

[csharp]
public class RequiresAuthenticationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//redirect if not authenticated
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
//use the current url for the redirect
string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath;

//send them off to the login page
string redirectUrl = string.Format("?ReturnUrl={0}", redirectOnSuccess);
string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;
filterContext.HttpContext.Response.Redirect(loginUrl, true);
}
}
}
[/csharp]

Now that we have this class defined, let’s create our custom membershipprovider class.
Firstly, create a class with the name ‘BugBaseMembership’ and let it implement the MembershipProvider interface:

implement membershipprovider interface

Now scroll down to the last method:

implement3

Here you can implement your own validate user method. And our backend is of course MongoDb so here we go:

[csharp]
public override bool ValidateUser(string email, string password)
{
using (var session = new MongoSession())
{
User user = session.users
.Where(u => u.Email == email && u.Password == password).FirstOrDefault();
if (user == null) return false;
else return true;
}
}
[/csharp]

Next, create an AccountController and implement the Login method:

[csharp]
namespace BugBase.Controllers
{
public class AccountController : Controller
{
public ActionResult Logon()
{
return View();
}

[HttpPost]
public ActionResult Logon(string email, string password, string returnUrl)
{
// Basic parameter validation
if (String.IsNullOrEmpty(email))
{
ModelState.AddModelError("email", "You must specify a mailaddress.");
}
if (String.IsNullOrEmpty(password))
{
ModelState.AddModelError("password", "You must specify a password.");
}

if (ViewData.ModelState.IsValid)
{

BugBaseMembership provider = new BugBaseMembership();
bool loginSuccessful = provider.ValidateUser(email, password);

if (loginSuccessful)
{
SetAuthenticationCookie(email);
return RedirectToAction("Index", "Bug");
}

else
{
ModelState.AddModelError("_FORM", "The username or password provided is incorrect.");
}
}

// If we got this far, something failed, redisplay form

return View();

}

public virtual void SetAuthenticationCookie(string username)
{
FormsAuthentication.SetAuthCookie(username, false);
}

public void Logoff()
{
FormsAuthentication.SignOut();
Response.Redirect("/");
}
}
}
[/csharp]

When the logon is successfull, you are directed to /Bugs/Index and the authentication is set. Which means that you can retrieve the logonname from the user during the session (User.Identity.Name returns the current logon name).

We’re not there yet. We have create a View for the user to enter Username and Password.
It should be strongly typed View and derive from the BugBase.Models.User class.

[csharp htmlscript=”true”]
<label for="email">email</label>
<label for="password">password</label>
<input type="submit" value="Log in" />
[/csharp]

There is one thing left to do. We need to plug our custom membership system into the website.
Open web.config and add the following in the System.Web section:

implement4

There you go. You just created your own custom membership provider with a MongoDb backend. Pretty easy, no?

You can download the codesample here.

9 thoughts on “ASP.NET MVC 2 and MongoDb Part 3 – Custom membershipprovider”

  1. Hi,In your post you said:”This is just to get you started! It’s not a very tightly secured authentication system, so don’t use this in production. In production you’ll probably want to use SSL and encrypted passwords.”
    i know how to encrypted passwords but i don’t konw how to use SSL,can you make a demo ?

  2. Well, using SSL is actually something you configure in IIS. You’ll have to create a binding, so that the website listens to port 443. Then you’ll have to buy a certificate (at Thawte, Verisign, Digicert or create a cert yourself with SelfSSL) and apply the certificate to your site. So, using SSL does not alter your code.

    Here’s a howto: http://learn.iis.net/page.aspx/144/how-to-set-up-ssl-on-iis-7/
    And with SelfSSL: http://blogs.iis.net/thomad/archive/2010/04/16/setting-up-ssl-made-easy.aspx

    Hope this helps!

  3. nice post,
    sorta inpired me to write a simple membership provider in case some needs it, basically just reference the dll, and and check the example for web.config confs.
    github link

Leave a Reply

Your email address will not be published. Required fields are marked *