You are currently browsing the category archive for the 'Retrieving User Specific Data With ASP.NET Membership a' category.

Objective: This article describes how to create a session variable and use it to hold the logged in user’s user name from the Membership Provider.

Background: ASP.NET Membership Provider server controls are a powerful and feature rich set of tools to create secure login, registration and password retrieval pages with drag and drop ease. There are however a few puzzling aspects for the newcomer to ASP.NET. By default, the membership provider creates a separate standalone database called aspnetdb.mdf. This can be a problem for many users if their hosting service provider allow only a single database per account. Fortunately we can overcome this problem by adding a custom membership to an existing database described in a separate article called “Adding The Membership Provider To An Existing Database“. This also solves the second problem which is the relational aspect of our database. It would be hard to create relationships between individual databases without some fancy footwork.

But even if we can add the Membership Provider to our already existing database so all the tables are in one place, how do we create the relationships necessary without understanding how the “SqlMembershipProvider” works, how and where it stores the user account information. Well, for an in depth explanation, the following nine part article series is an excellent choice.

http://aspnet.4guysfromrolla.com/articles/120705-1.aspx

Fortunately for you and I, we really don’t need to understand every aspect of the membership system to take advantage of all the cool features and functionality and security that it provides. Here are a couple of things to know: The SqlMembershipProvider handles almost everything for us. It makes sure that user names are always unique, it provides secure authentication for us, it takes care of account abuse, it provides us with new account creation, password recovery and countless other functionality that can be accessed through a few lines of code and/or the use of drag and drop server controls.

Once a user account is created, we can use that information to create and retrieve general and/or user specific information. If we closely examine the Membership tables created for us, we can clearly see which ones are of particular interest. These are:

  1. aspnet_Membership
  2. aspnet_Users

We can also observe that fields like:

  1. ApplicationID,
  2. UserID, and
  3. Password

fields are automatically encrypted for us to provide further security and assure uniqueness. The UserName column in the aspnet_Users and the Email column in aspnet_membership are however plain text. This is good news for us because this allows us to easily retrieve this information without any fancy footwork encryption and decryption know-how. The relationships between all of the SqlMembershipProvider tables are also automatically handled for us so we don’t have to worry about them.

Through the use of ASP.NET forms we can control the flow and validity of information that is input by a user and is destined for our database. We can create just the needed fields, apply validation controls and assign static or dynamic data to hidden fields. So, getting back to the relationship aspect of our data tables, here is what we need to do:

  • Our user specific table needs to contain a UserName column and an optinal UserID column so each row of data entered can be made unique for a specific user. When data is entered by or for a specific user, we can take the login UserName and UserID (a globally unique ID) from our session variables and assign it to a hidden field in the form. This information is then inserted into the table along with whatever else we have in the form.
  • We can then create a Foreign Key relationship between the aspnet_Users table (userID field) and our own custom tables that stores information specific to our users. When doing this, we have to make sure that these fields are of the same data type and length. They can however have different column names.
  • Once we have these in place, we can then start creating unique data that can be easily worked with.
  • We use the UserName when working with user specific data and use the unique userID for cascade update and/or delete when account information changes. For example: We can insert new data for a specific user, update or delete individual rows without effecting the membership account, or we can delete a membership account and automatically cascade delete all associated user specific data so as to not leave any orphaned data behind.

Procedure: Follow instructions below to accomplish this task. This article uses MSSQL Server Express 2005 and Visual Web Developer Express 2008.

How to retrieve the currently logged in user’s UserName and userID and put it in a session variable:

On the login form where you have your login server control, we would have the following code between the script tags or in the code behind page.

'.............Retrieve User Name and Assign it to a Session Start...............
'when the login control is submitted
'if the login button was triggered with CORRECT UN and PW then
'create session variable and set it equal to the current UserName
'create session variable and set it equal to the current UserID
'end if statement
'end subprocedure
Protected Sub Login1_Load(ByVal sender As Object, ByVal e As System.EventArgs)

    If User.Identity.Name <> "" Then

        Session("UserLogin") = User.Identity.Name
        Session("UserID") = Membership.GetUser(HttpContext.Current.User. _
        Identity.Name).ProviderUserKey.ToString()

    End If

End Sub'.............Retrieve User Name and Assign it to a Session End............... 

..Or, you could do it with cookies like the following sample:

'.....................Retrieve User Name and Assign it to Cookie Start................
'when the page loads
'if the login button was triggered with CORRECT UN and PW then
'create cookie variable and set it equal to the UserName
'create cookie variable and set it equal to the UserID
'write the UserLogin cookie to a label (optional)
'write the UserID cookie to a label (optional)
'end if statement
'end subprocedure
Protected Sub Login1_Load(ByVal sender As Object, ByVal e As System.EventArgs)

    If User.Identity.Name <> "" Then

        Response.Cookies("UserLogin").Value = User.Identity.Name
        Response.Cookies("UserID").Value = Membership.GetUser(HttpContext.Current.User.Identity.Name).ProviderUserKey.ToString()

        lblUserLogin.Text = Request.Cookies("UserLogin").Value
        lblUserID.Text = Request.Cookies("UserID").Value

    End If

End Sub'.....................Retrieve User Name and Assign it to Cookie End................ 

You would also need to create an event procedure for the membership provider’s logout button or link to explicitly destroy the custom session so as to free up server resources.

'If the logout button is clicked
'explicitely end all sessions
'end subprocedure
Protected Sub LoginStatus1_LoggingOut(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.LoginCancelEventArgs)
    Session.Abandon()
End Sub

We could also do something like the following example on the pages where the user specific information is displayed from the database that checks if our custom session still exist. For example, if the Membership Provider session which is separate from our custom session still exists but our custom session has timed out, we can quickly recreate our custom session or else redirect the user back to the login page.

'when the page loads
'if the membership session is still active and
'the UserLogin session is still active
'else
'if membership identity is still active
'but our custom session has expired
'then recreate the session for UserName
'recreate the session for UserID
'else
'for good measure abandon all sessions
'and redirect the user to the login page
'end all if statements
'end subprocedure
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)

    If User.Identity.Name <> "" Then
        If Session("UserLogin") <> "" Then
        Else
            If User.Identity.Name <> "" Then
                If Not Session("UserLogin") <> "" Then
                    Session("UserLogin") = User.Identity.Name
                    Session("UserID") = Membership.GetUser(HttpContext.Current.User.Identity.Name).ProviderUserKey.ToString()
                Else
                    Session.Abandon()
                    Response.Redirect("~/Login.asp")
                End If
            End If
        End If
    End If

End Sub

If you are hosting your application on your own IIS server, you can adjust the amount of time for session timeout. If however you are hosting with a web hosting company, the default timeout will usually be 20 minutes unless you ask them and they are willing to make changes for you.

Note: Using session variables to store larger amounts of data is bad practice all around although are in common use for many different reasons the popular of which are shopping carts. If your site has lots of users around the clock, cookies are a much better choice. Using sessions to hold login information for small to medium traffic sites however is acceptable but care should be taken to always explicitly destroy a session upon logout. There is a good reason why the default time out is only 20 minutes and the case of smaller web hosting companies it may be even less to save and or free up unused server memory. The reason for this is that most people don’t use the logout link or button but simply close the browser or navigate away from the site. This type of change is not detected by the server and the session stays active for the duration of the default timeout.

Cookies in general, especially if encrypted (recommended) are not hugging any server resources but with all the configuration option of most modern browsers, you may run into a problem if the user has turned off the accept cookie function. There is however an even bigger problem. Encrypting cookies in asp.net 2.0 and above that are not part of the membership provider class is a nightmare. There is information about how this is done but to this date I have not found a practical and rational way. Here is an article if you think it’s worth your time: http://www.codeproject.com/KB/web-security/HttpCookieEncryption.aspx .