Do most people use .NET's SqlMembershipProvider, SqlRoleProvider, and SqlProfileProvider? - c#

Do most people use .NET's SqlMembershipProvider, SqlRoleProvider, and SqlProfileProvider when developing a site with membership capabilities?
Or do many people make their own providers, or even their own membership systems entirely?
What are the limitations of the SQL providers that would make you roll your own?
Is it easy to extend the SQL providers to provide additional functionality?
For Reference
Per Scott Gu's Blog, Microsoft provides the source code for the SqlMembershipProvider so that you can customize it, instead of starting from scratch. Just an FYI.

We use everything except the Profile Provider. The Profile Provider is completly text based and does full text seearches - this becomes exceedingly slow as you user base gets larger. We have found it a much better solution to "role our own" profile section of the membership api database that is keyed to the userid in membership.

I've rolled my own MembershipProvider classes using derived MembershipUser types to wrap the custom user schema, so profile-style properties are now available everywhere as part of the derived user via a cast.

I normally use the providers that come out of the box, the main problem I have is querying across profile attributes across users. For example finding all users that have a profile attribute called Car that equals true. This is down to the way they are stored in the underlying structure.

I've used SqlMembership before and it's quite nice, unless you need something custom. I remember needing something like firstname and lastname info and I realised there're no fields for that. In the end instead of extending I've used Comment field of the provider and added name info to there. This is probably a bad practice/lazy/hack way but it worked for me in a tight situation..

In theory they sound nice, but not a chance if you do any unit testing without creating lots of abstract wrappers.

If you only need the basic user support (roles, profiles, etc.) then the default providers will work great.
If you need more customized support (data storage in a database not supported by the default providers [like Oracle], provider on a database that already exists, a heavily customized schema) then you should roll your own providers.
As for me, my current site only needed basic Roles support (and minimal Profiles support), so I went with the default providers.

I have used both the custom classes and built in. When you need to get to a different database or schema or need to have extra info.
I abstracted out the layers so that it would work on the logic layer and have a DAL layer that used the data.common.dbprovider bit so it was reasonably generic.

Related

AspNetCore Identity combined with application specified Groups or Customers

I am testing out Identity for my ASP NET CORE MVC application. From what I have read the Identity solution provided is probably the way to go now considering user management and security for logins.
What I have not yet understood is if it is somehow possible to combine the Identity solution with custom groups?
Let me explain..
Lets say I create a webpage for Factories.
This means that several customers that own these Companies that run the factories would like to use this system.
Company A has 3 Factories with 100 workers on each factory.
Company B only has one factory with 20 workers on that factory.
I have read alot of roles and that of sort on how we could seperate these by roles. What they can see, what they can do. But how in the world do I isolate Company A from Company B?
The old fashioned SQL table way would be like to have a Users table, a factory table and a perhaps Customers table. And from there build the logic. But with Identity it does not seem to work in that way?
Any suggestions or links to further reading about this would be appriciated! And even if you guys know that Identity is not the way to go for this kind of solution, then be it. Just so I don't waste any time on something that perhaps is not meant to be.
There's a lot to unravel in your question, but I'll give it a shot. At a high-level it sounds like you're looking for a multi-tenant system.
and pretty much everything you're saying is on point, you probably just need an example to get going. If so, check out Microsoft's example of a multi-tenant system. It might be enough to get you going.
There's several different approaches to a multi-tenant system depending on your business requirements, but here's a few of the more common approaches I've seen used:
Database Isolation - Each Company would be in a separate database. When a user from Company A connected, you would be able to look up which database/schema you should connect too.
Row Level - All companies store data in the same tables, but there's a column called something like "company_id". Every time you query against the table, you filter on company_id based on which user is logged in.
Instance per tenant (AKA Standalone) - On this approach you essentially have multiple web servers running, one per company. They are completely isolated from the web server all the way down to the database. This can be desirable in some situations, but requires a bit more hardware. On the code side, you can handle this fairly effectively with just moving relevant settings into the appsettings file.
Further Reading:
Identity Management In Multitenant Applications
Multi-Tenant Patterns on SQL Databases
Row Level Multi-Tenant Example
The implementation for the different companies changes depending on how you decide to implement the multi-tenant system. So it's hard for me to give you any concrete advice on implementation.
The only word of warning I'd give is think through the relationship between a user and a company. That could change/complicate your implementation fairly quickly.
Can a user be part of Company A and Company B at the same time?
Hope this helps a bit, and best of luck.

Logging Data Base changes using Entity Framework and ELMAH (or else)

Our customer request the functionality of logging changes in db.
We need next structure:
"Timestamp", "User", "DB.Table.Field changed", "Value after change"
What we have:
Entity Framework Code First
ELMAH
MySQL Data Base with more than 100 tables (changes should be tracked to all of them)
So we need:
Somehow track what table was changed
What new value was added/updated
Generic functionality (if possible)
Any ideas how to do this?
PS. ELMAH is not a strict requirement. But MySql is :)
Thank you!
Ultimately, what you're looking for is some sort of behavior that keeps track of auditing. ELMAH is not geared towards that.
You most likely want to look in to some sort of Polymorphic object that can keep track of who executed what type of action on a known entity. You're most likely going to want to use some sort of AOP concepts. Libraries like like DynamicProxy2, LinFu should be helpful in this area.
Your goal would be to use proxy objects that wrap your existing entities and "inject" the auditing information that you need to track.
I actually had the same feature request and even though I wrote a tracking layer before for my generic repository I found that there is one available in Nuget/Github that handles this.
https://www.nuget.org/packages/TrackerEnabledDbContext/
https://github.com/bilal-fazlani/tracker-enabled-dbcontext
You can use this and I found that it works great for me. I use it into my Generic repository project.

ASP .NET Membership customizing

After I was learning about ASP .NET Membership built-in framework I have decided that this stuff is almost suitable for me. But there are couple features and edits I would like to have:
Two step registration: after user have typed all account information, verification letter should be send to typed email. Before email address is verified it impossible to log in (some message should appear, telling user that email verification is needed before it's allowed to use account).
Membership DB Scheme:
There is no need to store user question for restoring password.
Illegal attempts to login is uneccessary.
Default aspnet_ prefix is likely to be changed.
... and so on
For the first item I know that I could use own class derived from SqlMembershipProvider. Am I right about this? Could you point me at some good post where I could get learned.
For the second improvement it's seems like a trouble. In this book I have read that isn't so easy:
• The built-in SQL storage providers need direct access to your database, which
feels a bit dirty if you have a strong concept of a domain model or use a particular
ORM technology elsewhere.
• The built-in SQL storage providers demand a specific data schema
that isn’t easy to share with the rest of your application’s data
schema.
The biggest problem I've encountered with subclassing SqlMembershipProvider is it doesn't give you the connection string to work with. You have to hack the class to pieces to get anything useful for the way most modern login systems work.
I'm not sure about the database tables names - I don't think that's controlled by the SqlMembershipProvider but is actually inside an ASP.NET installer class.
My advice would be to create your own from scratch, and use the built in FormsAuthentication helpers. It's really not a big task compared to hours of annoyance having to conform to the providers. I did this with Roadkill after going down the Membership Provider route, and discovering it a cul-de-sac particularly for Active Directory support.
You can completely control your membership DB schema by Implementing Custom Membership User (of course you also need to implement Membership Provider for the User).
Customize user creation steps by configuring CreateUserWizard control. You will change its' template and handle events, I don't think you need to override it.

How can I add relationships to the aspnetdb database in MVC?

I'm having a hard time wrapping my head around how to use the Memberships in MVC. I know there is the built in ASPNETDB database which has all the basic tables for users and such. But what if I wanted to add a relationship between one of my custom tables and this built in user table?
If I had a database table that contained blog comments, we'll call it Comment. And each Comment had a userID associated with it could I do something like?
User.Comments.Add(someCommentObj)
Anyone know of a good article on this? Is this even possible?
Thanks
Have a look at this extensive article on the MembershipProvider:
https://web.archive.org/web/20211020202857/http://www.4guysfromrolla.com/articles/120705-1.aspx
Look at Part 6 and 7, you'll probably want to implement a custom ProfileProvider and store the comment reference in the Profile.
Part 6 - capture additional user-specific information using the
Profile system. Learn about the
built-in SqlProfileProvider.
Part 7 - the Membership, Roles, and Profile systems are all build using
the provider model, which allows for
their implementations to be highly
If you want to use your own custom membership tables then you'll need to build your own MembershipProvider. Matt Wrock has a walkthrough:
You'll notice that the default AccountModel allows you to inject your own provider:
public AccountMembershipService(MembershipProvider provider)
{
_provider = provider ?? Membership.Provider;
}
Nerdinner has an example of dependency injection that you would probably find useful:
Warning Here are two solutions that will work. The first one is easy. The 2nd one, I think is what you're after, but take it for what it's worth. Make sure you realize what you're doing, since this will take the membership provider data and access it directly, which could result in some hidden bombs if you're not careful (like deleting data).
The membership data is meant to just be used for authenticating; roles for authorizing; profiles for user speicific data (like time zone or favorite color.
Solution One
If you wanted to add a comment under the current user (or any user) you could do:
var comment = new Comment(....);
comment.userId = User.Identity.Name; //for user name
or
comment.userId = new Guid(Membership.GetUser().ProviderUserKey); //for guid in table
That's the eays way and you never really have direct access to the aspnet tables, you just use its info.
Solution Two
I'm assuming that you're using L2S and the designer in VS.
By adding the membership table(s) to your L2S design, you will get access to its data. This may even be preferable for some quick querying (like dates, lock out info, etc. since you don't have to use the built-in sprocs which have some serious over-kill and heavy code). If you create a relationship in the DB or in the L2S designer, you'll have a relationship that you can access like your question asks.
At this point, the designer has created your classes for comments and users. If you do anything with the actual user table you just created, you're circumventing the membership provider's design - don't do this unless you now what you're doing. When you add a comment to the User, it will add the comment to the comments tables with the correct relationship intact.
You should now be able to do:
var user = MyUser.GetById(userId);
user.Comments.Add(comment);
Remember, that the User in this case is different than when you do
var user = Membership.GetUser(userId);

Custom Security in ASP.NET MVC For Applications (Not mass market web sites)

I'm building a SaaS app and have some issues in dealing with authorization and ASP.NET MVC. I have a previous question and this is kind of taking a cue from comments there. I need to provide somewhat granular security (e.g. lots of permissions) for each user. I realize that any discretionary system can be modeled as a roles system by just creating more roles. But that's a lot more roles than I want to deal with. I don't think roles is going to work for me and would like to work more at the permissions level.
I know the standard response to any question dealing with ASP.NET and authorization is create all your application users as Windows users and implement the ASP.NET Membership Provider. One issue, I'm not going to create Windows users. My question is can the standard ASP.NET MVC AuthorizeAttribute and AuthorizeCore be made to fit with a permissions model?
Also, apparently, the impetus here is really that ASP.NET MVC Caching will break a custom security implementation. Obviously, I don't want my pages to run slowly but I'm not sure I want this caching at all. I'm building a business application; is caching everything really appropriate? It seems that caching would just make concurrency problems much more difficult than they already are. For example, if I am caching all of my customer info pages, including the edit pages, then won't I be defeating any concurrency controls I would have in place (say, timestamp checking)?
If I were you I wouldn't create the users as Windows users, but rather store them in a SQL database. So you now have complete control over how you want to associate your security needs with your users.
Once you do that you can then create a custom security filter by creating a class that implements IAuthorizationFilter. That way you have the control you want to do whatever validation you want, roles based, permissions based, day of the week based, whatever.
You then just attribute your service methods with your new custom security filter, and pass along whatever info you need to ensure that the calling user has the appropriate rights/roles to execute the method.
First of all, you do certainly not need to make application users windows users. the default out of the box MVC has them as users stored in a sql database.
Edit Pages typically should not be cached as they will not really be loaded multiple times with the same data within the cache lifespan. my thought process is that MVC is easy enough to add caching that I would build it out first then performance test to see if it is even a necessary step. (Remember that unless you are looking at large large numbers of client connections then it is typically more economical to make a slightly less performant code and beef up the server hardware.
You do not need to create Windows users to use the ASP.NET Membership provider, it uses SQL tables to store the membership objects. Yes, you can use the Authorize attribute with the membership provider, for example, in a page that only "admins" can edit, you'll use the authorize attribute as follow:
[Authorize(Users = "Admin")]
Also, you don't want to be caching pages where users are going to be editing data, use caching (and you can do it a lot) in areas designated for anonymous users - users with no edit rights.
Hope this helps.

Categories