what's the best?
use a profile table to store information that's not present in membership table (like country, age, etc.), or customize a membership?
thanks
Membership data should typically be comprised of information that relates to authentication. i.e. security.
Profile is typically the appropriate place to store user meta data. i.e. personalization.
These 2 types of data serve different purposes and the segregation enables a clean separation of concerns in the providers.
An exception to this could be considered if there is some non-standard meta data that directly relates to authentication/authorization.
Whenever possible, it is best to use the built in providers. This reduces the amount of code you have to design, implement, test and maintain. And Membership, i.e. security, is not something that you want to find bugs in.
So, I would consider using the tried, tested and true membership provider and if you want table based meta, use a custom profile provider such as http://www.asp.net/downloads/sandbox/table-profile-provider-samples
Related
I'm building a new website and a friend suggest to me to use the asp.net membership for the authentication process (login, registration, password recovery, etc..).
I saw that everything is stored in an XML file.
I would like to know what are the pros and cons using the membership instead of to build something from scratch.
The MS login solution consists of several parts.
Authentication - "Who can access your site"
Forms Authentication - This basically creates a secure cookie that says "I'm authenticated!" on every request. Without this, users would have to log in every single page.
Pros: This works well
Cons: None - use it
Membership - This is how you store your users and their passwords, and validate user credentials. There are several ways to approach this:
Using the SqlMembershipProvider - Microsoft gives you a database to store users/passwords in securely, and gives you a way to authenticate credentials.
Pros:
Less/no custom code to maintain. Works "out of the box"
Works with Membership controls and API
Cons:
You have to use a Sql Server and use their database schema. (not a problem IMO)
No control over how passwords are initially generated. They're long and ugly
Steeper learning curve as you get familiar with the technology
Creating a custom MembershipProvider - You can inherit from MembershipProvider to customize where and how you store your data.
Pros:
You get Encryption/Decryption of passwords for free
Control over where you store your users and what the data looks like
You can still use the Membership controls and API
Cons:
Have to implement your own storage solution
You have to write, debug, and maintain a lot of custom code
If you add additional functionality, you have to cast the provider to use it
Creating your own Authentication scheme
Pros: Complete control
Cons:
You create everything, but have to debug/maintain everything.
You have to control security over credentials yourself.
Can't use Membership controls (This isn't a big loss as the controls are pretty simple to replicate)
Can't use Membership API
Authorization - "What can the users do?"
Roles - Roles control what the users can do via the authorization mechanism provided by the web.config and also works with security trimming on the sitemap.
Using the SqlRoleProvider - Microsoft gives you a database to store roles
Pros:
Works with the web.config
You can assign more than one role to a user
Cons:
Roles are just a string, no "hierarchy of permissions" support. This can make it difficult to create rules around which users can edit other users.
Creating a custom RoleProvider - You can inherit from RoleProvider to customize where and how you store your data.
Pros: Works with the web.config
Cons:
Have to implement your own storage solution
Still just a string and are as limited as the previous solution
If you don't implement it correctly, it could do a lot of database calls.
Creating your own Authentication scheme
Pros: Complete control - Just do custom checks on your page and error/redirect as necessary
Cons:
Doesn't work with the authorization mechanism provided by the web.config / sitemap. Practically this means that adding a page to a folder (such as /Admin) no longer guarantees security on that page.
It's important to note that the Membership and Role providers can be chosen or customized independently of each other. I would personally recommend using the SqlMembershipProvider if you can and evaluating your options for the Role Provider.
I dont like to use Membership Provider.
This is util when the scenario is "standard", but in cases that you need more custom rules, I think that dont works well. Appear "workarounds".
And not need store in a XML, exists another solutions (database, for exmaple).
Cons:
Your preferred datastore might not be fully supported out of the box
It might not match your current or future requirements
You might not fully understand the intricacies of how it works (over something you built yourself)
Pros:
You might save time compared to rolling your own.
Personally... if this is a serious project I would roll your own (but of course keep forms authentication). In my experience a lot of these 'out of the box' features from MS are rather half-assed.
The nice thing about ASP.Net Membership is that you can use as much or as little as you like - you can store user data in various forms (as others have mentioned), or you can just use ASP.Net Membership to handle session authorisation and page protection.
For example, you can go the whole hog and use the login control, the SQLMembershipProvider back end and just let ASP.Net Membership do everything end to end.
Or you can store your own usernames and passwords, in your own database table, authenticate the supplied details yourself and then simply just use "FormsAuthentication.RedirectFromLoginPage()" to tell ASP.Net membership that the user is authenticated, and have ASP.Net Membership then control access to pages.
ASP.Net Membership is tried and tested, its used by thousands of sites inside and outside of Microsoft, so you know the code works and works well. If there is an issue, then there are many implementations out there that will find it. Your own approach just has one user...
Actually, everything is not nessicarily stored in an XML-file. You can store the membershipdata in several ways, including a database.
You can also use the ASP.NET roles/membership library as a starting point for rolling your own. There are a few tutorials on doing this around the interwebs.
The pros with using the built-in functions is that the ASP.NET membership gui-controls more or less "just work".. ;)
In my opinion, the .NET membership providers are a great way to go regardless. I have written quite a few large applications using them. If your architecture is good, it's fairly simple to add functionality and change data in future releases.
Here's a bit of context to frame my answers. The membership/role/profile solutions in .NET consist of two parts: the framework and the providers. The framework consists of the methods and information your program will interact with. The providers determine how the data will be stored.
I find that the framework is excellent. There isn't much that you can't do regardless of how you want to interact with it. The default implementations do give you a lot for free. Any lack of functionality is further mitigated as a con if you are using good coding practices. See the starter ASP.NET MVC application for an excellent example of wrapping the membership framework.
The data never seems to work out the way you want, but it's nothing you can't work around. First as folks said, there are a bunch of providers shipped with .NET. And this is also where implementing your own provider comes into play. We usually start by subclassing SqlMembershipProvider. If something doesn't work the way we want, we override it. And changing the data tables at a later time if needed is not terribly difficult.
Using what already exists always seems to let us get going quickly and adapt as needed. In truth changes to this code don't happen often. Using the Microsoft solution at the beginning might not result with the prettiest piece of work, but it gets the job done quickly and lets you move on to solving important problems.
We are developing an ASP.NET MVC Application that currently uses it's own database ApplicationData for the domain models and another one Membership for the user management / membership provider.
We do access restrictions using data-annotations in our controllers.
[Authorize(Roles = "administrators, managers")]
This worked great for simple use cases.
As we are scaling our application our customer wants to restrict specific users to access specific areas of our ApplicationData database.
Each of our products contains a foreign key referring to the region the product was assembled in.
A user story would be:
Users in the role NewYorkManagers should only be able to edit / see products that are assembled in New York.
We created a placeholder table UserRightsRegions that contains the UserId and the RegionId.
How can I link both the ApplicationData and the Membership databases in order to work properly / having cross-database-key-references? (Is something like this even possible?)
All help is more than appreciated!
In my opinion, you should be able to integrate your database with the standard aspnet_db reliably, but I would advise against duplicating or replacing the aspnet_users table.
That is the focal point of all the providers that use the aspnet_db schema, including custom providers that may augment but do not implement custom replacement.
To maximize reuse of strong tested infrastructure code in the provider stack/API it is best to go with that flow.
You will want to be very attentive to any modified membership core functions and ensure that the way your new constraints behave in an expected fashion in each case.
The facet of the membership story that I have found needs the most attention is deleting a user, and a simple modification/addition to the delete user sproc can manage this capably.
It sounds like you might need to create your own customized Membership Provider. You can probably (not positive here) extend the existing one so you don't have to completely reinvent it. Here is a video from ASP.net that describes how to do that. Google "asp.net membership provider" for tons more.
You can try rolling your own membership or just extend is like Dave suggests.
Create your own [Users] Table which can be populated based off the aspnet_Membership table. So therefore you could have more control over it.
You could also just implement a more involved Profiles system. The .NET team has improved the way profiles are stored now, so instead of "blobicizing" them, you can set them up to be stored in an actual table now [thank god].
Table Profile Provider
If you find the right articles, it's really easy to extend the membership provider to allow for extra functionality. I've moved my users table to my main SQL server table and have written my own role manager that gets values from a separate table. What it sounds like you need to do is to set up a table in your users DB with the location of each user, then create a method on the user object something like "GetLocation()" that returns the user's location from the DB, you could then user that to filter your data from your main DB. Here's a few articles I had kicking aroundin my bookmarks, see if they help, if you have a look on the main ASP.NET site or google for membership provider extending articles, there are plenty around.
http://msdn.microsoft.com/en-us/library/ms998347.aspx
https://web.archive.org/web/20211020202857/http://www.4guysfromrolla.com/articles/120705-1.aspx
http://msdn.microsoft.com/en-us/library/aa479048.aspx
As the others have pointed out there are many good resources available that can help you with creating your custom provider using the existing database.
It looks like you are headed in the right direction with mapping tables. I think the one piece you are missing is Distributed Queries. This link is specific to Sql Server 2008. There is a link there to the documentation for Sql Server 2005 if that is what you are using.
I have an existing database with users and administrators in different tables.
I am rewriting an existing website in ASP.net and need to decide - should I merge the two tables into one users table and just have one provider, OR leave the tables separated and have two different providers.
Administrators, they need the ability to create, edit and delete users. I am thinking that the membership/profile provider way of editing users (i.e.
System.Web.Profile.ProfileBase pro = System.Web.Profile.ProfileBase.Create("User1");
pro.Initialize("User1", true);
txtEmail.Text = pro["SecondaryEmail"].ToString();
is the best way to edit users because the provider handles it? You cannot use this if you have two separate providers? (because they are both looking at different tables).
Or should I make a whole lot of methods to edit the users for the administrators?
UPDATE:
Making a custom membership provider look at both tables is fine, but then what about the profile provider? The profile provider GetPropertyValues and SetPropertyValues would be going on the same set of properties for users and admins.
Probably you should merge the two tables into one and use a RoleProvider to make the distinction between administrators and "normal" users.
Alternatively, you could implement your own, custom membership provider, which would use both tables.
Mike,
My advice is to go ahead and merge your two 'membership' tables and segregate admins from non with roles.
(This is, I know a duplicate of the previous answer but I feel the need to explain..)
In this way, unless you have some compelling reason to implement custom providers, you will be able to leverage the stock providers and database structure to provide a robust user management story for your website without writing any code (that you have to test and maintain).
.2 pesos....
In the current project I'm working on, we are using the asp.NET profile to store information about users, such as their involvment in a mailing list.
Now, in order to get a list of all the users in the mailing list, I cannot simply do a database query, as the asp.NET profile table is, simply put, awful.
For those who do not know, the profile table has two main columns, the 'keys' column, and 'values' column, and they are organised as so:
Keys:
Key1:dataType:startIndex:endIndex:key2:dataType . . etc.
Values:
value1value2value3...
This is pretty much impossible to query using SQL, so the only option to find users that have a specific property is to load up a list of ALL the users and loop through it.
In a site with over 150k members, this is understandably very slow!
Are there specific reasons why the Profile was designed like this, or is it just a terrible way of doing dynamically-generated data?
I agree that it's a pretty bad way to store profile data, but I suspect the use case was just to get the profile data for a user with a single query but in such a way that it can be extended to handle any number of different profile properties. If you don't like it, you can always write your own, custom profile provider that separates each value out into its own column. Having implemented various membership and role providers, I don't think that this would be too complicated a task. The number of methods doesn't look too large.
The whole point of the Provider model is that it abstracts away the data source. The idea is that, as a developer, you don't need to know how the data is stored or in what format - you just have a common set of methods for accessing it. This means you can swap providers without changing a single line of code. It also means that you specifically do not try and access data direct from the data source (eg. going straight to the database) by bypassing the provider methods - that defeats the whole point.
The default ASP.NET profile provider is actually very powerful, as it can not only store simple value types (strings, ints etc.) but it can also store complex objects and entire collections in a single field. Try doing that in a relational database! However, the downside of this generic-ism is that it comes at a cost of efficiency. Which is why, if you have a specific need, then you are supposed to implement your own provider. For example, see SearchableSqlProfileProvider - The Searchable SQL Profile Provider.
Of course, your third option is to simple not use the profile provider - nobody is forcing you to! You could implement your own classes/database entirely, as you would have had to do in other frameworks.
I have implemented various custom providers (membership/Sitemap/Roles etc) and havent really looked at the ASP.NET Profile Provider after seeing that kind of thing (Name/Value pairs or XML data). I am not sure, but I think the Profile is primary created for User Preferences/Settings where the settings are only required for a specific user, I dont think the Profile is meant for User "Data" that can be queried?
Note: This is an assumtion based on what I think I know, please comment on this otherwise.
I am looking into building an authentication in my ASP.NET application with the following requirements.
A user has exactly one Role (i.e. Admin, SalesManager, Sales, ....)
A role has a set of permissions to CRUD access a subset of existing objects. I.e.
"Sales has CREAD, READ, WRITE permission on object type "Products" but not DELETE"
Somehow I like the permissions to be in a hierarchy with inheritance so that I for i.e. Admin don't need to specify all available objects.
The system must quickly be able to answer the question "Does user X have permission to do Y to object Z"
All database managed (MSSQL), implemented in C#/ASP.NET
I would like to get feedback on these requirements? Any ideas how to implement this using ASP.NET framework(as much as possible)? (However, I'm also interested to know how this can be achieved without Memberships)
I think what you need to do here is implement a set of permissions query methods in either your business objects or your controller. Examples: CanRead(), CanEdit(), CanDelete()
When the page renders, it needs to query the business object and determine the users authorized capabilities and enable or disable functionality based on this information. The business object can, in turn, use Roles or additional database queries to determine the active user's permissions.
I can't think of a way to declaratively define these permissions centrally. They need to be distributed into the implementation of the functions. If you want do improve the design, however, you could use dependency injection to insert authorizers into your business objects and thus keep the implementations separate.
There's some code that uses this model in Rocky Lhotka's book. The new version isn't in Google yet.
I think one of the best implementations that I think will fulfill your requirements is documented here. The only issue is that this hooks into NHibernate, but you can use this as a template to create your own permissions implementation and simply hook into your own event model rather than that of NHibernates Interceptors.
I am working on such a system myself and will blog it once I am happy with it.
The membership API provided since ASP.NET 2.0 should suit your requirements well. The only thing I'm afraid it doesn't directly support is hierarchical roles. However you can easily use normal role based security with another manually written hierarchical roles table to achieve the required things.
You can read on how to set up ASP.NET Membership here: http://msdn.microsoft.com/en-us/library/yh26yfzy.aspx
It allows you to group folders / pages etc into Groups / Users. I think you will find this sufficient!
The hiarchy is easily managed by extending the generated databases and procedures.
I would build the user/role relationship so users can have more than 1 role. I see a 1-1 relationship and I get nervous because I know that even if we don't see a need for it now, someone is someday going to want someone to be both a Sales user and a Customer Service user.
In our customer system, we use roles to layer on stuff like "delinquentCustomer." That way, the original permissions are still valid--as soon as they pay their bill. Worth considering this approach.