views:

367

answers:

1

I am using the Membership Provider in ASP.NET MVC and for most data access I use nHibernate and a repository pattern. Do you recommend using a Facade over the Membership Provider so I can create a repository and make it operate a bit more inline with the rest of my entity model? I also have added additional functionality like the ability to add functions to a role and creating the facade would make the classes all a bit nicer.

What have other people done with Membership Provider?

A: 

I have solved this exact problem. In the following manner:

web.config:

<authentication mode="Forms">
  <forms name="APPAUTH"
   defaultUrl="/webapp/Home.mvc"
   loginUrl="/webapp/Session.mvc/Login"
   protection="All"
   timeout="30"
   path="/"/>
</authentication>
<authorization>
  <deny users="?"/>
</authorization>

<location path="Session">
  <system.web>
 <authorization>
   <allow users="*"/>
 </authorization>
  </system.web>
</location>

Then I hook Application_AuthenticateRequest something along the lines of:

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
 string cookieName = FormsAuthentication.FormsCookieName;
 HttpCookie authCookie = Context.Request.Cookies[cookieName];

 if (null == authCookie)
 {
  //no authentication cokie present
  return;
 }

 FormsAuthenticationTicket authTicket = null;
 try
 {
  authTicket = FormsAuthentication.Decrypt(authCookie.Value);
 }
 catch (Exception)
 {
  // Can't do anything if we can't decrypt the ticket so treat it as not there
  FormsAuthentication.SignOut(); // Remove bad ticket
 }

 if (authTicket == null)
 {
  //could not decrypt cookie
  return;
 }

 // get the role
 string[] roles = authTicket.UserData.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

 // Set the security context
 ISecurityService security = ContainerProvider.RequestContainer.Resolve<ISecurityService>();
 Models.User user = security.GetUser(authTicket.Name);

 if (user == null)
 {
  FormsAuthentication.SignOut();
  throw new HttpException((int)System.Net.HttpStatusCode.Unauthorized, "Session expired!");
 }

 AppIdentity id = new AppIdentity(user, !authTicket.Expired);
 AppPrincipal principal = new AppPrincipal(id, roles);

 Context.User = principal;
}

The ContainerProvider.RequestContainer.Resolve<ISecurityService>(); call is to a Autofac container, but you can do anything you need to / want to here.

The AppIdentity and AppPrincipal classes are custom so I can access my roles, but they are not that complicated.

Andrew Burns