Watch videos with subtitles in your language, upload your videos, create your own subtitles! Click here to learn more on "how to Dotsub"

[How Do I:] Create a Custom Membership Provider?

0 (0 Likes / 0 Dislikes)
  • Embed Video

  • Embed normal player Copy to Clipboard
  • Embed a smaller player Copy to Clipboard
  • Advanced Embedding Options
  • Embed Video With Transcription

  • Embed with transcription beside video Copy to Clipboard
  • Embed with transcription below video Copy to Clipboard
  • Embed transcript

  • Embed transcript in:
    Copy to Clipboard
  • Invite a user to Dotsub
Hi, this is Chris Pels. In this video we're going to learn how to create a custom ASP.NET Membership Provider. To implement a custom membership provider, what we need to do is create a class that inherits from a base membership provider class and then implements the number of abstract properties and methods that are required by that base class. So let's go ahead and create a class library project here. And we'll call this MembershipProviderVB, and we'll put this class in a folder here. Now we're going to need a couple of references for this in order to implement the provider. So let me just show all files, and we'll add a couple of references. You need to add two actually, and the first one is System.Configuration, and the second one will be System.Web. Now that we have those references, the next thing we need to do is take our Class1 here and inherit from the base class I mentioned that has the abstract properties and methods. And that is in System.Web.Security.MembershipProvider. And once you hit the Enter key here, we'll see the stubs for all the methods that we need to implement. Now as you can see from the list of methods here in the drop down, there are quite a few methods and some properties that we need to implement. So in the interest in time, what I'm going to do is bring in a class that I've already implemented all these properties and methods so we don't have to spend a ton of time looking at the development of the code but can focus more on what these methods do and how they're implemented. So let's go out here, and we'll take the project, and let's refresh it. And here is the class that I want to bring in called DHIMembershipProvider. So we'll include that in the project, and we'll also delete Class1 here because we're not going to need that anymore. Before we take a look at the implementation of the methods for the membership provider base class, we need to create a place to store our membership data. Now if we were using the SQL membership provider that comes with ASP.NET, there's a script that creates a variety of tables and stored procedures for the membership data. However, since we're creating a custom provider here, what we want to do is have our own place to store membership data. So let's go over to SQL Server and take a look at how we're going to do that. There's a table here called Users, which will be used to store our membership data, and there's a variety of columns that are contained in it. Most of these columns coincide with the need to store certain pieces of information to implement the functionality required by the methods in our base class. And we'll refer back to these columns as we go through the code and look at the implementation of some of that functionality. Now we happen to be using SQL Server in this sample, but you could easily use another database, say Microsoft Access, Oracle, etc. to store your data. So now let's go back over to Visual Studio and take a look at the implementation of our membership provider class. So let's take a look at the implementation of our custom membership provider. As you can see, the HDIMembershipProvider inherits from the base membership provider class, which is required for any custom membership provider. Now what I've done here is to group various sections of the class into regions so it makes it a little easier for us to take a look at things given that there's just over 1200 lines of code in the class. There's a number of import statements up top just to make it easier so we don't have to type fully qualified namespaces. There's a number of class-wide variables here that are used at various points of the functionality in the methods of the class. Then we have our first override here of the application name property from the abstract base class. And all this is doing is storing and retrieving the name of the application in one of those class-wide variables that we just saw above. Then we have several other properties here that are also implementing overrides of the abstract base class. We have one for the enabling of resetting a password, one for whether or not the password can be retrieved, whether or not the provider requires that a question and answer be part of the registration or create user process, whether or not there is a unique email required in the membership process, the number of—or rather the maximum number of invalid password attempts that the user can make when logging in, as well as the window of time, in minutes in this case, that we count invalid password attempts. Also there is one for what format we use for the password, and we'll see that in a little more detail in a minute. Whether or not we require a minimum number of non-alphanumeric characters, and also what the minimal required length of the password is. And then lastly, what the strength regular expression is. Now those of you who have worked with the SQL membership provider that comes with ASP.NET, a number of these properties should be familiar to you, as they are attributes that are base set in the web.config file when you specify the membership provider. Actually, when we put this custom membership provider into a website to test it, you'll see that some of these will be set as attributes of our membership provider in the web.config file. So let's close up the properties here. Then the first method from the base class that we're implementing is the Initialized method. And essentially what happens here in the Initialized method is that we're retrieving a number of values from the web.config file. So for example, let's take line 172 here. And what's happening here is that we're going out to the web.config file, we're getting the max invalid password attempts attribute, and we're storing that in the class-wide variable of the same name. What I've done here in this class is to try to be consistent in the naming conventions so that you'll see many of the class-wide variables are named such that they correspond to the values in the web.config file as well as the properties that use those class-wide variables. And the last thing we do here with the config information is we bring in the password format. And then based upon what value that is in the web.config file attribute, we set the class-wide variable password format to the corresponding standard enum value for membership password format. Next we go down here and get the connection string from the config file. And then lastly what we're doing is bringing in the machine key section of the web.config file, which as you can see by the comment here on line 107, has to do with encrypting and decrypting our key information. Now there is quite a few methods from the base class that are implemented here. So what I want to do is just pick a couple of these methods. We'll look at how they're implemented and what the approach is. And then you can look at the other methods in your leisure by downloading the sample source code because there's a lot of consistency across the methods in terms of the approach. So let's take a look first at the create user method because this is a very important method in our membership provider. So what the create user method does is it receives inbound a number of pieces of information from the base class. And then once the user is created, there is a membership user object that's returned, and this is the standard membership user object that would be returned by any other provider including the default SQL membership provider. So all we're doing is just interceding in the process and getting the information for the membership user and populating that object on our own. So the first thing that happens here in the create user method is we setup that the user will be validated once we've created them by creating an instance of the arguments for validating the password and then calling the OnValidatingPassword method. Then if we get a cancel return from these arguments in the call to the validating of the password, we set the status to invalid password, and we actually don't create the user and just return from the method. Next we take the email address, and we determine whether or not the current settings require a unique email, and if so, then we go out to the database and see if a user already exists for the email. Then if they do exist, we set the status to duplicate email, and we return from creating the user. Next down here on 361 we take the user name, go off to the get user method, and see whether or not we get a membership user object back or whether we get a membership user object that's populated with data because if we do not get a membership user back, that means the user doesn't exist in the database, and then we can go forward with creating the user. So to create a user we have to setup a number of parameters that are passed into the stored procedure. In this case it's called User_Ins. And most of these values come inbound to the CreateUser method. You'll recognize many of the names. And then once we've set up the parameters, we execute the stored procedure to determine whether or not it was successful. If it is, we set our status to success. Otherwise, it is set to reject it. And then once we know that our user has been successfully created, down here on 397 we call the GetUser method passing the user name, and it returns a membership user object instance, which is then returned from the CreateUser method. Next let's take a look at the ValidateUser method. And this method is called every time your try to log into the system with a user name and password. So let's see how that one works. So the user name and password come inbound to the method, and when we're done we return true or false whether or not we validated our user. So the first thing that we do here in the method is to take the user name and execute a stored procedure that goes off and gets us the password that's currently on file for the user. And this particular stored procedure is called User_Validate. We go off, we execute that, open up a SQL data reader, and we get some of the values, as I said, from that reader or the row corresponding to the user in the table in the database. One is the password that's currently on file, and the second is whether or not the user is approved. Now once we have that information, we call a CheckPassword method, which is your utility method here in the class that takes the inbound password to the ValidateUser method and compares it with the password that's stored in the database. And I want to take a look at this because the CheckPassword method contains the logic that allows us to compare our inbound password, which is in plain text format, to the stored password, which may or may not be hashed. So let's go down to the definition of the CheckPassword method and see how this works. Entered and stored passwords come inbound here. And then based upon what the format of the password is, in this case we are dealing with encrypted or hashed passwords. Let's say we have a hash password. What happens is we then call this EncodePassword method takes the plane text password that the user typed in and encodes it. And then we compare whether or not it's equal to the one that comes from the database. That EncodePassword method is right down here. And one important thing to note is that it is using the machine key section from the web.config file, and similarly there is an Unicode method down here if our password was encrypted. So let's go back up to our ValidateUser method. So if after checking our password the two passwords are equivalent, then we look to see whether or not the user is approved. If they are approved, we consider this a valid user. And then we make a call to a stored procedure, which updates the log in date for the user so that we're able to keep track of the date and time that each user logged into the system. Now if our password check failed, what would happen is we would call a separate utility method, which updates the database to indicate that our user tried to log in, but it failed. And then finally down here on 930 we return the local variable _isValid, which indicates whether or not the user was successfully validated. The third method I would like to have us look at here is the ResetPassword method. What this does is it takes in the user name and the answer to their security question and ultimately returns the new password. So the first thing we have to do starting on 766 is find out whether or not the user has enabled— or the application allows users to reset their password. If not, we throw an exception. Otherwise, we move on. Then we look and see if the user didn't supply an answer to their security question, and we are required based upon our configuration to have an answer to a security question. We update the failure count for the user and throw exception. However, if that all looks good, then we create a new password using the GeneratePassword method in the .NET Framework membership namespace—or class rather. And we use—the link of the password comes from the configuration file as well the minimum number of required non-alphanumeric characters. Now once we have that new password, we take the user name and the new password and call the OnValidatingPassword. Then we test to see whether or not that was successful. If it is successful, then we call a stored procedure User_GetPasswordAnswer. The purpose of this stored procedure is to take the user name and the application and retrieve for us the answer on file to the user's security question as whether or not they are currently locked out because they've exceeded the maximum number of password attempts. So following the call to that stored procedure, the first thing we do is get the value from the result set that indicates whether or not the current user is locked out. If they are, we throw an exception. And if they are not locked out, then we take the answer from the result set and store it in a local variable. Next, if we are required by the configuration settings to have an answer to a security question, we then call a CheckPassword method. But this time we're passing an answer provided by the user to the answer from the database. And this same method that checks the password actually compares the two answers and tells us whether or not they're equivalent. If they're not equivalent, then we update the failure count for the current user and throw an exception. If they are equivalent, then we call another stored procedure down here, which updates the password for the user, and inbound it takes the new password here. Let me just scroll over to the right so you can see that. And it encodes or encrypts the password and passes that in as a parameter to the stored procedure. And it's stored in the user's record in the database. And finally once that's all done, we take the new password and return it from the ResetPassword method. Now there are a host of other methods here that you can see, and most of these methods follow a very similar approach. They either get values from the database, update values in the database, compare some values that are either passed into the methods to configuration values, etc. to determine whether or not the purpose of the method is being carried out. What I'd like to do here before we leave our custom membership provider and actually create a sample website and implement it is just go back over to SQL Server, and we'll take a quick look at the various stored procedures that are used here just so you get a perspective on what those stored procedures are. And as with the additional methods in the actual implementation of the provider, you can take a look at these stored procedures in the sample code. So now let's go back over to Visual Studio and test out our custom membership provider in a sample website. So let's create a sample website where we can test out our custom membership provider. First let's build the provider to make sure that we've done everything correctly. And it looks good. So now we'll create a sample website. And we'll just create a regular ASP.NET website. And let's call this WebsiteVB. So the first thing we want to do here on our website is add a reference to the custom membership provider that we created over here in the class library. Now what we're going to do is add that reference directly to the project in our solution. You could also create a Bin folder on your own and copy and paste the assembly into the Bin folder. So now that we've included the reference of our custom provider, we want to add some membership configuration information into the web.config file. So we'll go down here, and what we want to add is a membership element. And we'll set the default provider to be HDIMembershipProvider. Then we want to add the element for the providers. We'll clear any existing providers, and now we're going to add our new provider. Let's give it a name equal to HDIMembershipProvider. And next we'll enter the type attribute. This is the fully qualified class name, so in this case it'll be HDI.AspNet.Membership.HDIMembershipProvider. We'll set the connection string for our provider, and that is equal to HDIConnectionString, and that's the find up above in the web.config file in the connection string settings—or rather elements. And let's enable password retrieval. Equal to true. And let's also enable password reset. True for that one. And let's require a question and answer. And that looks good. So this provider here in the web.config file rather than membership provider that we've defined here will cause our website to use the custom provider rather than any other provider such as the SQL Membership Provider that comes with ASP.NET. And before we leave the web.config file here, I just want to point out up here on line 55 is the machine key element with the key values that are used for encrypting or hashing of the password as we saw when we were looking at the custom membership provider code. So let's close this down here. And now what I'd like to do is create a few pages. And on our default page what we'll do is we'll just say this is the how— put a little label so to speak— How Do I, and this is the custom membership provider. And this is just a simple little label so that when this page comes up, we know what it is. Then there's two other pages that I'd like to create to test out our provider. And the first one is going to be a page called CreateUser, which we'll do as the name implies. And then the other is a login page, and we'll just name that one Login. So let's put a login control here on our login page. We'll go over to the toolbox, down under login we'll get a login control, drag it over here onto our login page, and put that in there. And let's go over to our create user page and take one of those standard create user wizard controls and put that here as well. And now we should be all set to test out our little website that will use our custom membership provider. Before we test out the website, what I want to do is open up our custom membership provider class and set a few breakpoints. And the first one I want to set is up in the CreateUser method. And then the second one will be down in the ValidateUser method. So now we're all set to go. Let's just make the create user page our start up page. We'll start up the website in debug mode. We'll get the standard create a user form from the create user wizard control. Let's fill this out. We'll call this testuser1. Password, we'll make password. Email, we'll make [email protected] Security question, let's use favorite dog, and that would be Dino. Now when I click create user, you'll see we jump into the CreateUser method, and it goes through all the logic that we just saw when we reviewed that class. We'll let that go. We end up in ValidateUser, and here it would go through all the logic to determine whether or not the current user is valid that we saw. And when we finish up with that, you'll see we successfully create a new user. We'll click continue. And since we're now authenticated and logged in, we have access to our home page. So now let's go back, and this time we'll make the default aspx be the homepage. And I should note that all of the access for anonymous users has been turned off here. So whenever we try to access any page including the homepage, we'll be asked to authenticate. So now let's start it up again. And this time we're redirected to the login page. Let's login as testuser. And put in the password. Click login. We end up in validate user again. It goes through that logic. And when it's complete, it authenticates us, and we're redirected to the homepage. Let's just shut down the browser here, and I want to go back over to SQL Server and just take a quick look at the database table users where we're storing our information. And you will see here we do have one row for testuser1, so the information that we entered in our create user form was stored in the database. So that's an example of two of the major operations in our custom membership provider, creating a user and validating a user. As you saw when we went through the code, there's a lot of properties and methods here from the abstract base class that are implemented. And what I encourage you to do is download the sample source code, install it on your machine, and use breakpoints as a means of stepping into various operations such as entering too many invalid passwords. So in summary, what we did is we created a custom membership provider by creating a class library, and in it we had a class called HDIMemebershipProvider that inherited from the abstract base class of membership provider from the .NET Framework, and then we implemented a number of abstract properties and methods from that base class. I hope you enjoyed this video on how to create a custom membership provider. This is Chris Pels. Thank you for your time.

Video Details

Duration: 29 minutes and 3 seconds
Country: United States
Language: English
License: All rights reserved
Genre: None
Views: 5
Posted by: neudesicasp on Aug 26, 2013

A Membership Provider allows a web application to store and retrieve membership data for a user, and the standard ASP.NET Membership Provider uses pre-defined SQL Server tables. In this video we learn how to create a custom membership provider that uses custom SQL Server tables separate from the pre-defined tables used by the standard provider. The principles covered in the video will apply to creating custom membership providers using other databases such as Access or Oracle. After learning to create the custom membership provider, we learn how to configure the provider in a web application, and see a demonstration of creating a new user and authenticating the new user with the custom membership provider.

Caption and Translate

    Sign In/Register for Dotsub to translate this video.