I've done MVC in the past, but I am new to ASP and ASP MVC. I really love the ease that ASP MVC provides me, so far, but I am having trouble figuring out how to get more control over the Users. By default, the MVC provides a minimal user registration form. I have looked around quite a bit, but I still have two questions:
How do I make the User data base a local database in my project? I think SQLEXPRESS is used to store the user values, in what seems like a magical process. How do I de-magic-ify this? I would like to have more control on the location of this database.
This leads to another question: How do I expand the User? I have been reading up on Profiles, but I am still confused about a few things. How do I prepare a Profile and link it with a User? What serves as the foreign key? And, in my controllers, how can I access various parts of the user like username, email, or even from the profile stuff like firstname, lastname (though I guess once when I have a Profile's database and a User's database locally, I can run sql commands to retrieve data)
I would really appreciate some pointers to the right resources, and/or best practices with ASP.NET
I would start by reading this official Microsoft article on extending the ASP.NET Membership API. It talks about creating extra tables for storing additional information about users.
The membership database
If you have an existing database which holds all your other website information, you can run the aspnet_regsql.exe tool to generate the necessary user tables. You will then need to modify your web.config and add the SqlMembershipProvider along with your connection string.
If you're creating a new project and don't have a database, start with a new MVC project which already has Membership enabled. Your database will be created inside the App_Data folder on first use, and you can take this and attach it to your SQL/SQLEXPRESS server. Then it's just a matter of changing the connection string to use a DB server rather than a local file.
Creating additional tables
This part is actually quite simple and consists of a few short steps:
Create a new table, i.e. UserProfiles
Add a uniqueidentifier column as your primary key, and add a foreign key to the aspnet_Users table
Add any other fields you want to store (Phone, Address, Gender etc.)
If you're using LINQ-to-SQL or the Entity Framework, you can simply drag the tables you need onto the designer, and you'll be ready to query the Membership tables.
Here's a little sample on usage
Add this snippet to your repository responsible for Profile/Account information.
public aspnet_User GetUser()
{
MembershipUser user = Membership.GetUser();
return db.aspnet_Users.SingleOrDefault(u => u.UserId == user.ProviderUserKey);
}
Then inside your models, you can get the user and access the other information stored in your UserProfiles table.
AccountRepo accountRepo = new AccountRepo();
aspnet_User user = accountRepo.GetUser();
string Address = user.UserProfile.Address; // bingo!
And that's pretty much it!
This is obviously a simple example, and you should be checking if the user is null and you could also create a class responsible for returning the necessary information about a user, implement caching, etc..
I would start from here:
Managing Users by Using Membership
Managing Authorization Using Roles
Also a great article series (18 articles!!!) is from Scott Mitchell at 4GuysFromRolla.
The ASP.NET membership model is desgned to have a pluggable architecture. You can write you own MembershipProvider implementation that best suit your needs.
Even if most of the samples you will find on the net regards ASP.NET web forms, there are only very small differences when used with MVC.
If you're still looking for insight into this, I just ran across the fact that in MVC 4 WebPages sites, there's a provider called the SimpleMembership provider. It gives more control to the developer of the Users, Roles and Membership info stored on websites. More here:
http://blog.osbornm.com/archive/2010/07/21/using-simplemembership-with-asp.net-webpages.aspx
Related
I've just started with MVC after working on Web Forms for 4 years. I've watched few videos explaining the architecture/fundamentals and I'm now able to replicate few modules of my old project with MVC5 using EF6.
I've a SQL Server DB containing tables such as Albums/Artists/Titles/Reviews and he User Table. I was able to work with the first set of tables using EF6 just fine including inserts/deletes. The prev project I had implemented custom Web Forms authentication using BCrypt by storing the details in the User table and later doing the validations and setting the auth cookie.
User table has details such as UserId, PWHash, EMail, FirstName, LastName. The UserId is a FK in the Reviews table and few others.
The implementation I'm hoping for is as below:
1. Login screen accepts credentials and validates with existing User table.
2. If valid, move to the 2FA screen(eMail/SMS).
3. If valid, then allow access to application.
Most of the tutorials say how to extend the attributes such as FirstName/LastName but do not say how to use an existing DB. I'm planning to use bcrypt/scrypt to encrypt the sensitive details.
I've gone through MVC 5 & ASP.NET Identity - Implementation Confusion but id doesn't have all the answers to my queries
I just need the starting point on how to plug the existing DB instead of using the dbcontext provided by default
Personally I find the documentation quite frustrating as well when you move away from th conventional, so you may be in for a world of pain.
The easiest way would be to fully take control of the authentication process yourself, utilising FormsAuthentication
However, if you want to leverage a lot of the out the box code, that has been delivered with MVC5 but against a custom database, or schema you will probably have to implement your own UserStore and maybe UserManager among other things.
The problem is, there is a lot to implement, so you are going to have a fun time guaranteed.
Have a read through this article on Custom Storage Prodivers to get a head start.
Good luck
If your app is using EF Code First then you can use your existing schema and plug in your own user. Look at the following example which shows how you can reuse your existing user information and plug it into Identity http://aspnet.codeplex.com/SourceControl/latest#Samples/Identity/CustomMembershipSample/Readme.txt
You do not have to inherit from the IdentityDbContext. You can directly use the DbContext. In this case you will have to override the onModelCreating to create the Users/ Roles tables and all the mappings between the tables.
Background:
I'm incorporating the SqlMembership provider into an existing system where I'm building a web front end. The Membership database will be kept in a separate database.
Beyond the login account, there's an additional mapping between the accounts that needs to be in place in the main database in order for an account to be able to log in.
Let's say that this table gives the user the right to use the system.
My question:
I would like to somehow incorporate this into the provider. Is it possible without too much work? (Or is it better to keep it in the AccountMembershipService class?)
Actually regardless, I'm very interested in learning how to put additional login requirements into the provider.
I'm asking this because when I've been looking at creating a custom membership provider earlier it seemed at that time a little bit overwhelming.
In other words:
I want to understand how to extend the Membership Provider classes in general and how to extend the login method (ValidateUser) in particular.
Given the sample ODBC implementation It looks like one simply could subclass the default provider and override ValidateUser calling base.ValidateUser as the first step.
However it may or may not be that simple, and I'd be very happy to hear any first hand experiences from implementing or extending membership providers.
I wanted to do something similar, one of the requirements was to use an Oracle DB, so I implemented the OracleMembership provider, hence I could not waste my time rewriting the hole oracle membership provider (it works pretty fine), the second requirement was to use a custom authorization legacy system. So I realized that the Internet Application template which comes with the MVC 2 or 3 comes with a small implementation of the security for the site, specifically take a look on the AccountMembershipService class. You could move all of these elements out of the MVC app to a separate assembly so you could use it even on a client implementation. The AccountMembershipService uses the Membership provider as the underlying authentication system with the option of using FormsAuthentication.
So I recommend you to take a look on that implementation. You could put your additional authentication code there so your application would stay cleaner and your don't need to re-invent the wheel and you have the chance to add your own code.
best regards
In order to extend the membership provider make you own tables with one to one relationship with the main database and handle additional requirements through this table. Also while implementing and extending the default membership provider you may need to store extra information in authcookies you may get additional information from here , here and here
In GetUserCredentials you will do your stuff for additional checking and RoleID is some dropdown on your login page that you will receive in the post method of sign in.
FormsAuth.SignIn(userName, rememberMe);
ApplicationRepository _ApplicationRepository = new ApplicationRepository();
MembershipUser aspUser = Membership.GetUser(userName);
SessionUser CurrentUser = _ApplicationRepository.GetUserCredentials(aspUser.ProviderUserKey.ToString(), RoleID);
if (CurrentUser == null)
{
ModelState.AddModelError("_FORM", "Invalid Role ");
FormsAuth.SignOut();
return View("signin");
}
How do I migrate users from a existing users table to Forms Authentication?
There seems to be three options:
T-SQL - Iterate through the existing users table and insert into Forms Authentication tables using the stored procedure aspnet_Membership_CreateUser
Code - create a utility that will iterate through the existing users table and insert into Forms Authentication tables using Membership.CreateUser()
Code - as users login verify credentials against existing users table and insert into Forms Authentication tables using Membership.CreateUser()
Which is the most practical?
I have been currently trying option 1 but I am running into difficulties using the password salt to create the encrypted password from a plain text password
With regard to #1, what exactly is the problem? You don't need to worry about the hashing if you've got plaintext passwords already. Just call CreateUser(username, password). Simple as that.
Have you considered implementing your own MembershipProvider class that hits only your user table?
Trying to synchronise data between two tables may seem trivial now, but may cause you a whole world of hurt in the future as your software evolves.
Just to confirm are you saying you've got an existing users table in your database and you want to use asp.net membership and the membership tables generated?
If that is the case you don't necessarily need to migrate your data. You could extend the membership provider and create your own membership that links into the existing table you already have.
Here's a couple of link if it helps:
Asp.net video
Writing A Custom Membership Provider
I'm trying to design an entity model for an application that uses ASP.Net membership for it's user authentication. In most of the database schemas I create, records typically end up related to users via the UserId field on the aspnet_users table. That's worked fine for me in the past, but now that I'm using EF, I'm having some conceptual issues with figuring out how I'm going to reference the user from an entity.
For example, let's say we have a "post" entity that contains a "postedBy" property. I'd LIKE to be able to do get the username of the user that created this post with something like post.user.username, but I'm wary of creating an entity based on the aspnet_user table for fear of creating a model that let's me bypass the Membership class when making changes to the database.
I've considered just leaving the post.userId field as a guid and then requiring that any code that needs to know the username use that guid to get the user from the Membership class, but that seems "ineligant".
Does anyone have any recommendations for entity model designs that integrate with Membership? I'd be reasonably happen with a "read-only" user entity.
My advice is: "Don't."
Let me be more specific.
Using UserId as a mapped, foreign key ties your entity model not to ASP.NET Membership in general, but to the SQL Membership Provider in general. What happens if you then want to use domain authentication or OpenID?
Don't get me wrong: 99.9% of the time it's correct to tie DB references together with a foreign key. Heck, you could even do it here, but don't map it into your entity model. You need to keep a wall of logical separation between membership providers and your own data. You access your data through the EF. You access membership data through the membership API. The fact that they happen to live in the same DB because you happen to be using the SQL membership provider is an implementation detail.
Update: I've expanded upon this idea in a blog post.
I've got a generic ASP.NET (MVC) application, that uses NHibernate as the model persistence layer, and ASP.NET Membership/role/profile services as the user management layer.
The question is what can be considered as the best practice to create linkings between the domain data and the users. (For example is I want to create a forum system I want to link each topics/posts to a specific user, and want to display the user at each request).
These are the posiibilites I've been thinking of:
Store the user ID in NHibernate (like having a Guid column in all your domain classes (Posts, Topics etc.) that needs to reference a User) and use GetUser each time you need the name of the user from the guid (which might result in n+1 queries)
B variant: Alternatively store the user name too.
Use the same database, and create a read-only NHibernate maintaned domain object User, that maps to the same data as the M/R/P services do.
Forget about M/R/P and create a separate user management service based on NHibernate
Forget about both and use J2EE/RoR/merb/DJango/etc. (please don't pick this option :) )
other...
I would go for step 2 (almost, as it does not necessarily needs to be readonly) and create a custom membership provider for NHibernate.
To save time you can use an existing one like the one from Manuel Abadia.
With that you keep the full power of NHibernate (lazy loading, etc.) and enjoy M/R/P services too.
There is also a NHibernate based Membership provider at CodePlex
4 guys from rolla have an excellent post if you want to buil your own provider on top of the asp.net membership API : https://web.archive.org/web/20211020114106/https://www.4guysfromrolla.com/articles/110310-1.aspx