from:http://osbornm.com/2010/07/21/using-simplemembership-with-asp-net-webpages/
With the introduction of ASP. Webpages and the WebMatrix stack our team have really be focusing on making things simpler For the developer. Based on a lot of customer feedback one of the areas so we wanted to improve is the built in security in ASP. So with this release we took, that time to create a new built in (and the default for ASP. Webpages) Security provider. I say provider because the new stuff is still built on the existing ASP. So what does we call this new hotness, which we have created? Well, none of the other thansimplemembership. simplemembership is a umbrella term for bothsimplemembership and simpleroles.
To the left was a diagram (you can click on it-see a bigger version) I often if explaining howsimplemembershipWorks to other team members. I'll admit I spent time making sure my boxes looked like boxes and had four points just for you guys. The middle section dotted in the blue are the existing membership APIs in the ASP. ThesimplemembershipAPIs is implemented as providers that is plugged into the core ASP.SimpleroleproviderSimply implements theRoleProviderAbstract base class and does not add anything more.Simplemembershipprovideris a bit trickier. To being able to support features I'll discuss later in the post we needed to add additional functionality so we created a NewExtendedmembershipproviderAbstract class. TheExtendedmembershipproviderAbstract class inherits from the core ASP.MembershipProviderAbstract base class. When you are using ASP. Webpages Both of these new providers are registered as the default membership and Role Provider S. We also added a newwebsecurityClass which provides a nice façade toSimplemembershipprovider. This class was a helper class designed to make some of the more common tasks easy when you are trying to secure your websit E.WebsecuirtyAlso holds APIs for some of the new functionality, we have added. For instance confirming an account and initializing the database (I-ll talk about this in just a minute). That's the basic overview of the internals to the newsimplemembershipFeature.
Okay Now, you have a basic understanding of what and why we created simplemembership i would like to SP End some time walking through how can I use it to secure your brand new ASP. Webpages site. There ' s too much to cover in a single blog post so I'll skim over some areas and ignore others, but would provide you enoug H information So, you can get started using simplemembership on your own. Also I do assume so you have a basic working knowledge of ASP. Webpages and the patterns that is used with this type of the framework. Okay So what am I going to show? I'll walk you through what to set up the database, create a registration page, create the login and logout pages, create A profile page, and finally create a simple admin sections to control it all.
Before we start the first step of setting up your database I would like to give you some background information. One of the biggest complaints from customers have been the lack of control over the users table. The default provider in ASP. gave you some generic information and then the ability to store other information in a "BL OB ". This worked off well if you were not trying to does anything complicated but if you wanted to something complicated it wasn ' t that easy. WithsimplemembershipWe decided that it is easier to allow you, the developer, to having control of the users table and letsimplemembershipHandle storing the authentication credentials. For example, you might already has a users table and want to integrate it withsimplemembership. AllsimplemembershipRequires is, there is, columns on your users table so, we can hook up to It–an "ID" column and a "username" Column. The important part of this they can be named whatever you want. For instance username doesn ' t has to is an alias it could is an e-mail column you just has to tellsimplemembershipTo treat this as the "username" used to log in.
Okay So let's get started creating our users table. In this example I'll be using the new SQL CE 4 Database Engine So in WebMatrix add a new Database file (this can is done On the Database Manager tab), name it whatever "I example I chose" Securitydemo.sdf ". Add a new table Called "Users" (once again you can call the tables and columns whatever to want I ' m just guiding you through my example) . The only of columns you is some ID column and some username column in this case I chose the very clever names "UserID" and "Username". Also add any and columns for data you would like to store and when you ' re do you'll have something like the table in the Image to the left. Although if you want to follow along add all the columns I had that the it would be is easier to copy and paste code.
Now, we have the created our users table we need the wire it up tosimplemembership so, simplemembership knows what columns to use. Now I'm going to introduce a new feature of ASP. Webpages that's or may not be know about which is the start page. This was a specially named page that would get run the first time an application starts. So create a page with the name "_start.cshtml" on your site, remove all the markup leaving only the code block at the top, and put the following code in that code block.
- Set Up Simple Membership
- Websecurity.initializedatabasefile ("Securitydemo.sdf", "Users", "UserID", "Username", true);
The parameters is rather self-explanatory but they is, in the following order, name of the database file, name of the T Able you is using for the users table, the name of the column being used for the ID, and the name of the the column is using for The username. If you notice I left the last one off because it isn ' t really self-explanatory, it's aBOOLValue tellingsimplemembershipTo create the tables it needs if they is not present. These is tables that is used under the covers to make everything work, for instance the roles table. Every table created by Simplemembership'll start with "Webpages_"In the name. As a general rule of thumb for later on if you have to manually query one of the tables with "Webpages_"In the name there are probably a better API to be calling. Now it's time to run your site once, these'll causesimplemembershipTo go and create the tables we need. When you ' re done, you'll have the tables in the image to the your database.
Okay so now, all set up and simplemembership are wired up to your table. The next logical step is to create a page where users can register for your site. Due to the fact, he post is already getting long I am not going to show you the whole page, just the key pieces of cod E and if you ' d like to see the whole page you can download the sample and use it to follow along. At this point, create a register page with input fields for each of the columns in your user table. When the page is posted-to-do some sort of validation on the values, you can download the sample and see the P Attern I use. If all the posted values is valid call the following code, where the anonymous object represents the columns in your user s table.
- Websecurity.createuserandaccount (username, password
- New{firstname = fname, LastName = lname, email = email, StartDate = datetime.now, bio = bio});
Now was the perfect time to talk about the words User and account. Basically the word user maps to the user table and the word account maps to the table simplemembership uses to store things like password salts and confirmation tokens. You can choose to use your own SQL INSERT statement to insert into your users table and then just wire that entry up To simplemembership But as a rather common task we created a helper for it.
The next logical set would is to create a through to login and logout of your site. Let's start with the login page. Once again I ' m skipping all the simple HTML markup and post data validation since we had a lot to cover.
- if (websecurity.login (username, password)) {
- var returnUrl = request.querystring[" ReturnUrl "];
- if (Returnurl.isempty ()) {
- Response.Redirect ("~/account/profile");
- } else {
- response.redirect (RETURNURL);
- }
- }
There is a helper method, that hangs off of the websecurity class, the use to login a user and it Would return true of false based on if the username and password combination are valid. There is one thing that I wanted to make sure that I pointed out here. If You remember this simplemembership is built on the core ASP. NET membership APIs when a user visits a part of the site T Hat requires authentication (I ' ll cover how to set this up in just a minute) they'll be redirected to the the login page (Default is "~\account\login"). When they is redirect the framework tacks on a query string parameter of " ReturnUrl " So can be used to return The user to the URL is they were trying to navigate to after they is logged in. You'll notice that in the code I check for that and if it's not empty I redirect them to that URL otherwise they get redir ECT to their profile page.
Now, can login to the site you need someone to being able to logout right? Logging out are much simpler, in fact the logout page does not has any markup it's simply a page that the website posts T O and then the request was redirected after the user was logged out.
- Websecurity.logout ();
- var returnUrl = request.querystring["ReturnUrl"];
- if (Returnurl.isempty ()) {
- Response.Redirect ("~/");
- } else {
- Response.Redirect (RETURNURL);
- }
I choose to keep the concept of a return URL because I wanted a user to being returned to the page where they clicked on the Link to logout. This makes for a nice touch and can really help user experience but it's not necessary that you could simple redirect them to The root of the site.
What good is have a login and logout page if there is no part of the your site that requires a user to be authenticated? In the example I choose to kill both birds with one stone and say so if a user is logged in and they visit their profile Page they is able to the change their password. This-I-get-to-show you guys II APIs instead of just one. For a cleaner look I had a conditional statement in the HTML markup that would leave out the change Password markup if " iscurrentuser "is false.
- //get The username from the URL e.g. account/profile/osbornm
- var username = urldata[0]! = string . Empty? Urldata[0]: websecurity.currentusername;
- var iscurrentuser = UserName = = Websecurity.currentusername;
-
- if (IsPost && iscurrentuser) {
- //if everything checks out try to Ch Ange the password
- if (val. Count = = 0) {
- if (! Websecurity.changepassword (Websecurity.currentusername, OldPassword, NewPassword)) {
- val. ADD ("Unable to change password.");
- }
- }
- }
The
There is a couple of APIs that I would like to point out in the code above. First off is that currentusername property hanging off of websecurity . If a user is logged in the This would be there username and if they was not logged in it would be a empty string. Also There is plenty of these helpers methods that's can use including one, requires an authenticated user Can put at the top of your page to require a user to is logged in to see that page. The second API I want to call out is ChangePassword , also hanging off of websecurity . This would return true is the successful or false if there was a problem.
Now, we have the basic functionality, the only thing left are to spice it up by adding some roles and a special section For administrators to do administrator stuff. The I ' m going to tackle this problem are to create parts of the admin sections and then use them to add the role and add The users to the role, once that's done we'll change it so is people in the admin role can access that page. Just like before I'll leave off the simple HTML markup and can download the sample if you would like to see it.
- Code to add a role
- var roleName = request["RoleName"];
- if (roleName! = null) {
- if (RoleName = = string. Empty) {
- Validation Message
- } else {
- Roles.createrole (RoleName);
- }
- }
The first thing I would like-to-point out is the. I wanted to any of the functionality on one page so that means there would be many forms all posting to this page. So what to I tell the difference from a post to add a role from a post to add a user to a role? I use the values, the come in with the request. If The post has a value of named " roleName " I know that it must had come from this form, that's what line three is Testing. While this isn ' t fool proof, it's simple and works with the most of the time and its fine for this sample. You'll notice that in the code sample we had reached a point where we aren ' t using the websecurity cla SS anymore, that ' s because, the core ASP. NET APIs work just fine. So we call the static ' createrole ' method on the Roles object, which under the covers ends up Calling the simpleroleprovider to Create the role.
Now, we can create a role we need a to add a user to that role otherwise there are no reason to has roles. I Choose a simple UI for this task that probably isn't the most efficient for adding lots of all users to lots of roles it Works fine for this example. So you'll notice in the code below that I grab all the users and all the roles so that a DropDownList c An is populated with the values.
- //code to get all users
- dynamic users;
- using (Var db = database.open ("Securitydemo")) {
- users = db. Query ("select * from [Users]");
- }
-
- //get The current roles in the system
- var roles = Roles.getallroles ();
-
- //code to add a user to a role
- var usertoaddto = request["Usertoaddto"];
- var roletoadd = request["Roletoadd"];
- if (!usertoaddto.isempty () &&!roletoadd.isempty ()) {
- Roles.addusertorole (Usertoaddto, roletoadd);
- }
The reason I choose to query for all the users myself are I wanted to show you that the developer really does own the US ERS table so can issue normal SQL queries to get info like this without have to go through all the membership APIs. Again, I followed the pattern of detecting values that came on from the request to determine what action needed to be perf Ormed. Once again the core ASP. NET APIs is good enough for adding a user to a role so can simply call the static method on T he Roles object.
Now, we had can go create the admin role and add our user to it, navigate to the page and does so, it's okay I ll WA it for you. Done? Good. So now that you ' re a admin on your own site let's go lock down this admin sections of the site so only users that is in T He admin role can access it. This is easiest do by moving, page to a admin folder and then using AN  init page . This is another one of those specially named pages (May) or may not be already know about. Basically create a page with the name , "_init.cshtml " in a folder and that page would run first before any Other page in this folder for every request. This was useful for doing operations such as requiring a authenticated user or requiring a specific role because the code is at one location and not spread across every page.
- Websecurity.requireauthenticateduser ();
- if (! Websecurity.iscurrentuserinrole ("Admin")) {
- Response.Redirect ("~/account/unauthorized");
- }
Just like the "_start.cshtml" file There was no markup Just a code block at the top. This code does the things; The first is to require a authenticated user This means if you visit part of the admin sections and you aren ' t logged in Y Ou'll get a nice prompt for your password. The second is so if a user is authenticated but they aren ' t in the "admin" role they would be redirect to an unauthorized Page I created that displays a nice error message explaining why they can see that part of the site. You don ' t has to do it it's that is could redirect anywhere you wanted for even set the status code to 404 so it looked l Ike there wasn ' t anything there, it ' s all up to you.
Well now you do, you have a very simple implementation that secures your site and can store user information. The sky really is the this limit here, there are so much more you can do, there were just too much to cover in one blog post. If you have requests-do something I ' d is glad to add an example or even create a new post about if you just hav E to let me know. Also in the downloadable source there are quite a bit more than what I covered here! I have examples of requiring a confirmation e-mail to being sent, deleting user and roles, using a layout page to display a lo Gin/logout status widget, and how to implement some simple validation based on the the-the-i-net MVC does its validation.
Using simplemembership with ASP. Webpages