Is it possible to create a login system with ASP.NET MVC but not use MemberhipProvider?

I have an existing database with a user table, and we plan to take the database and use it for the new system created in ASP.NET MVC. However, I am not sure that I can create a login system that does not use the built-in account controller or the regular membership provider so that we can use the existing table structure.

So my question is: is this possible? Or is it even especially difficult to do if this is so?

What is the most common way to do things and the simplest?

+58
authentication asp.net-mvc
Sep 17 '09 at 11:05
source share
4 answers

I had the same requirement. I had my own user and role scheme, and I did not want to migrate to asp.net membership scheme, but I wanted to use ASP.NET MVC action filters to check permissions and roles. I had to do quite a lot of digging to find out what exactly needs to be done, but in the end it was relatively easy. I will save you trouble and tell you what I did.

1) I created a class derived from System.Web.Security.MembershipProvider. MembershipProvider has a ton of abstract methods for all kinds of authentication related functions, such as a forgotten password, password change, creating a new user, etc. All I wanted was the ability to authenticate against my own scheme. Therefore, my class contained mostly empty overrides. I just overridden ValidateUser:

public override bool ValidateUser(string username, string password) { if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password)) return false; string hash = EncryptPassword(password); User user = _repository.GetByUserName(username); if (user == null) return false; return user.Password == hash; } 

2) I created a class derived from System.Web.Security.RoleProvider. Again, I just had empty implementations for all the fluff that I don't need, like creating and changing roles. I just redefined two methods:

 public override string[] GetRolesForUser(string username) { User user = _repository.GetByUserName(username); string[] roles = new string[user.Role.Rights.Count + 1]; roles[0] = user.Role.Description; int idx = 0; foreach (Right right in user.Role.Rights) roles[++idx] = right.Description; return roles; } public override bool IsUserInRole(string username, string roleName) { User user = _repository.GetByUserName(username); if(user!=null) return user.IsInRole(roleName); else return false; } 

3) Then I included these two classes in my web.config:

 <membership defaultProvider="FirstlookMemberProvider" userIsOnlineTimeWindow="15"> <providers> <clear/> <add name="FirstlookMemberProvider" type="FirstlookAdmin.DomainEntities.FirstlookMemberProvider, FirstlookAdmin" /> </providers> </membership> <roleManager defaultProvider="FirstlookRoleProvider" enabled="true" cacheRolesInCookie="true"> <providers> <clear/> <add name="FirstlookRoleProvider" type="FirstlookAdmin.DomainEntities.FirstlookRoleProvider, FirstlookAdmin" /> </providers> </roleManager> 

What is it. The default action filters will use these classes. You still have to process the login and sign up. Just use standard authentication classes for this, as usual.

+81
Sep 17 '09 at 14:44
source share

Whenever someone tells you that something related to security is β€œeasy,” they almost always make mistakes. In safety, there are many subtleties that are usually lacking.

In particular, any form of authentication that is clearly not related to caching is inherently broken. When the result of an action is cached, it happens in ASP.NET, not necessarily in the ASP.NET MVC stack. If you study the source code of AuthorizeAttribute, you will see that it contains a bit complex, but efficient code that ensures that it always works, even when the result of the action is cached.

The best way, by far, to configure ASP.NET MVC authentication is to write your own ASP.NET membership provider. I won’t claim it is safe, but there are fewer ways to get into a problem with a compromised security implementation on this route, and then in other ways. A significant advantage of this method is that you can replace another authorization system at almost any time without changing the code.

If you must implement the custom MVC attribute, then you must subtype the AuthorizeAttribute and override the AuthorizeCore, carefully following the comments in the source code regarding thread safety.

+11
Sep 17 '09 at 13:23
source share

Of course you can. I did this for my projects that completely ignored the membership provider.

You need to implement your own ActionFilter. Basically, it will take control before the controller action is executed. Inside it, you decide whether to continue the action or redirect the user to the login page.

For an attribute, you can define any parameters necessary to support your authentication / authorization model.

 public class AuthorizationAttribute : ActionFilterAttribute, IActionFilter { public MyRole UserRole { get; set; } void IActionFilter.OnActionExecuting (ActionExecutedContext filterContext) { // Decide whether to grant access to the action or redirect away } } [Authorization (UserRole = MyRole.All)] public class UserController : Controller { [Authorization (UserRole = MyRole.Admin)] public ActionResult Delete () { } } 

Regarding the problems expressed in the comments. Yes, enabling the output cache will interfere with authorization. You just need to know about it.

Explanation of the problem: ASP.NET MVC # 40 Tip - Do not cache pages requiring authorization

+10
Sep 17 '09 at 11:08
source share

You have at least two possibilities.

  • custom action filter attribute that will give you authorization check
  • custom IHttpModule , which will fill in all the necessary data for the registered user (including roles), and you can use existing action filters

The second option can be used with regular web forms.

+1
Sep 17 '09 at 11:22
source share



All Articles