Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Custom Membership Provider for very large application

I have to come up with a membership solution for a very large website. The site will be built using ASP.NET MVC 2 and a MS SQL2008 database.

The current Membership provider seems like a BIG overkill, there's way too much functionality.

All I want to store is email/password and basic profile information such as First/LastName, Phone number. I will only ever need 2 roles, administrators & users.

What are your recommendations on this type of scenario, considering there might be millions of users registered? What does StackOverflow use?

I've used the existing Membership API a lot in the past and have extended it to store additional information etc. But there's tables such as

aspnet_Applications
aspnet_Paths
aspnet_SchemaVersions
aspnet_WebEvent_Events
aspnet_PersonalizationAllUsers
aspnet_PersonalizationPerUser

which are extremely redundant and I've never found use for.

Edit
Just to clarify a few other redundancies after @drachenstern's answer, there are also extra columns which I have no use for in the Membership/Users table, but which would add to the payload of each select/insert statements.

  1. MobilePIN
  2. PasswordQuestion/PasswordAnswer (I'll do email based password recovery)
  3. IsApproved (user will always be approved)
  4. Comment
  5. MobileAlias
  6. Username/LoweredUsername (or Email/LoweredEmail) [email IS the username so only need 1 of these]

Furthermore, I've heard that GUID's aren't all that fast, and would prefer to have integers instead (like Facebook does) which would also be publicly exposed.

How do I go about creating my own Membership Provider, re-using some of the Membership APIs (validation, password encryption, login cookie, etc) but only with tables that meet my requirements?

Links to articles and existing implementations are most welcome, my Google searches have returned some very basic examples.

Thanks in advance
Marko

like image 353
Marko Avatar asked Nov 13 '10 23:11

Marko


2 Answers

@Marko I can certainly understand that the standard membership system may contain more functionality than you need, but the truth is that it really isn't going to matter. There are parts of the membership system that you aren't going to use just like there are parts of .Net that you aren't going to use. There are plenty of things that .Net can do that you are never, ever going to use, but you aren't going to go through .Net and strip out that functionality are you? Of course not. You have to focus on the things that are important to what you are trying to accomplish and work from there. Don't get caught up in the paralysis of analysis. You will waste your time, spin your wheels and not end up with anything better than what has already been created for you. Now Microsoft does get it wrong sometimes, but they do get a lot of things right. You don't have to embrace everything they do to accomplish your goals - you just have to understand what is important for your needs.

As for the Guids and ints as primary keys, let me explain something. There is a crucial difference between a primary key and a clustered index. You can add a primary key AND a clustered index on columns that aren't a part of the primary key! That means that if it is more important to have your data arranged by a name (or whatever), you can customize your clustered index to reflect exactly what you need without it affecting your primary key. Let me say it another way - a primary key and a clustered index are NOT one in the same. I wrote a blog post about how to add a clustered index and then a primary key to your tables. The clustered index will physically order the table rows the way you need them to be and the primary key will enforce the integrity that you need. Have a look at my blog post to see exactly how you can do it.

Here is the link - http://iamdotnetcrazy.blogspot.com/2010/09/primary-keys-do-not-or-should-not-equal.html.

It is really simple, you just add the clustered index FIRST and then add the primary key SECOND. It must be done in that order or you won't be able to do it. This assumes, of course, that you are using Sql Server. Most people don't realize this because SQL Server will create a clustered index on your primary key by default, but all you have to do is add the clustered index first and then add the primary key and you will be good to go. Using ints as a primary key can become VERY problematic as your database and server system scales out. I would suggest using Guids and adding the clustered index to reflect the way you actually need your data stored.

Now, in summary, I just want to tell you to go create something great and don't get bogged down with superficial details that aren't going to give you enough of a performance gain to actually matter. Life is too short. Also, please remember that your system can only be as fast as its slowest piece of code. So make sure that you look at the things that ACTUALLY DO take up a lot of time and take care of those.

And one more additional thing. You can't take everything you see on the web at face value. Technology changes over time. Sometimes you may view an answer to a question that someone wrote a long time ago that is no longer relevant today. Also, people will answer questions and give you information without having actually tested what they are saying to see if it is true or not. The best thing you can do for your application is to stress test it really well. If you are using ASP.Net MVC you can do this in your tests. One thing you can do is to add a for loop that adds users to your app in your test and then test things out. That is one idea. There are other ways. You just have to give it a little effort to design your tests well or at least well enough for your purposes.

Good luck to you!

like image 172
Kila Morton Avatar answered Sep 23 '22 01:09

Kila Morton


The current Membership provider seems like a BIG overkill, there's way too much functionality.

All I want to store is email/password and basic profile information such as First/LastName, Phone number. I will only ever need 2 roles, administrators & users.

Then just use that part. It's not going to use the parts that you don't use, and you may find that you have a need for those other parts down the road. The classes are already present in the .NET framework so you don't have to provide any licensing or anything.

The size of the database is quite small, and if you do like I do, and leave aspnetdb to itself, then you're not really taking anything from your other databases.

Do you have a compelling reason to use a third-party component OVER what's in the framework already?


EDIT:

there are also extra columns which I have no use for in the Membership/Users table, but which would add to the payload of each select/insert statements.

MobilePIN PasswordQuestion/PasswordAnswer (I'll do email based password recovery) IsApproved (user will always be approved) Comment MobileAlias Username/LoweredUsername (or Email/LoweredEmail) [email IS the username so only need 1 of these]

This sounds like you're trying to microoptimize. Passing empty strings is virtually without cost (ok, it's there, but you have to profile to know just how much it's costing you. It won't be THAT much per user). We already routinely don't use all these fields in our apps either, but we use the membership system with no measurable detrimental impact.

Furthermore, I've heard that Guid's aren't all that fast, and would prefer to have integers instead (like Facebook does) which would also be publicly exposed.

I've heard that the cookiemonster likes cookies. Again, without profiling, you don't know if that's detrimental. Usually people use GUIDs because they want it to be absolutely (well to a degree of absoluteness) unique, no matter when it's created. The cost of generating it ONCE per user isn't all that heavy. Not when you're already creating them a new account.


Since you are absolutely set on creating a MembershipProvider from scratch, here are some references:

http://msdn.microsoft.com/en-us/library/system.web.security.membershipprovider.aspx

http://www.4guysfromrolla.com/articles/120705-1.aspx

http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx

http://www.amazon.com/ASP-NET-3-5-Unleashed-Stephen-Walther/dp/0672330113

Stephen Walther goes into detail on that in his book and it's a good reference for you to have as is.

like image 39
jcolebrand Avatar answered Sep 24 '22 01:09

jcolebrand