ASP.NET Providers - Membership

This blog post is part of a series about the ASP.NET Providers (namely Membership, Role Management, and Profile). The introductory post in the series can be found at the following link, which introduces the Provider Model pattern and gives a personal example of an implementation I have been working on:

This post will deal with adding the Membership functionality to your website.

Membership Provider Configuration

Now that your DB is set up, there are a few snippets that need to be added to your Web.config. It involves adding a connection string and adding a new membership provider, as in the sample below:

<configuration>
<connectionStrings>
<add name="MyDB" connectionString="..." />
</connectionStrings>
<system.web>
... authentication & authorization settings ...

<membership defaultProvider="ConfiguredMembershipProvider">
<providers>
<add name="ConfiguredMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="MyDB"
applicationName="SampleWebSite"
minRequiredPasswordLength="5"
minRequiredNonalphanumericCharacters="0" />
</providers>
</membership>
</system.web>
</configuration>

WARNING: According to Microsoft, you should never use the default provider settings and should always add a new, configured provider; in addition you must be sure to specify the applicationName attribute! See Scott Guthrie's blog post on this topic for more details. Apparently, you can also use a value of "/" for the applicationName and it will use the root application name.

The last two attributes of the add node are only a couple of several membership features you can configure. For a complete list of attributes you can configure, see <add> Element for Providers for Membership.

Securing Site Content by Requiring Authentication

With 5 more lines of configuration added to your Web.config, you can have the whole site secured and accessible only by user account authentication. Even better, you can make that 6 lines added to the Web.config, add a Login.aspx page, and drop in a Login control from the Toolbox and you will get auto-redirect to the login page if someone tries to hit any page you've now secured. The framework is even smart enough to return you to that desired page after successful login; it accomplishes this by redirecting you to the login page but by adding a ReturnUrl query string attribute to know where to go after authentication.

Here are the additional lines for your Web.config (put them under the system.web node):

<authorization>
<deny users="?" />
</authorization>

<authentication mode="Forms">
<forms defaultUrl="index.html" loginUrl="Login.aspx" />
</authentication>

NOTE: You will likely already have an authentication node in your Web.config, but it's mode may be set to the default "Windows" value. To use the Membership Provider for authentication, you must have this value set to "Forms."

The optional 6th line I spoke of earlier is the forms node under the authentication node. The defaultUrl attribute of this line is used to tell the framework where to go after successful login if there is no ReturnUrl specified in the query string. The loginUrl attribute is used to specify the page the user is redirected to if they are attempting to hit a page that requires authentication.

The deny node is using the question mark (?) wildcard character, which is used for anonymous users (or those that haven't been authenticated yet); the asterisk (*) wildcard is used to signify all users browsing the site. Since we are dealing with the Web.config at the root of the site, this deny rule will apply to the whole site and it's subdirectories. You can either put a Web.config in each subfolder that requires an overriding or more restrictive set of allow and deny rules, or you can actually specify location elements in your Web.config, as is shown in the following example (basically you could have several of these location elements, each with their own authorization rules):

<configuration>
<location path="Login.aspx">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
</configuration>

As far as I can tell, this sample configuration above isn't necessary if you have specified your login page in the loginUrl attribute of the authentication/forms node like we did in the previous code snippet. But this sample is at least illustrative of the location-based authorization rules.

Personally, I decided to create a folder named Public in my site and I give it its own Web.config that allows all users (including anonymous ones) access to the containing web pages. This folder currently contains the login, user account registration, account activation (a link included in the email sent upon registration), and password retrieval pages, all of which would need unrestricted access for anonymous users.

Test Your Membership Provider

With all of this now in place, you should be able to use the ASP.NET Website Administration Tool launched from Visual Studio to create a few new user accounts. I mentioned how to launch this utility earlier in this series with a post titled ASP.NET Providers - Getting Started. Then you can double-check your membership system is working by logging in with your newly created credentials. Also, you can now create a user account registration page (utilizing the CreateUserWizard control) and a password retrieval/reset page (using the PasswordRecovery control). All of the controls I have named throughout this post are highly skinable and configurable via numerous attributes and templates; they also contain flexible task workflows that you can override or plug into by registering to any of several event listeners.

One other thing that needs to be done if you want to enable the email notification capabilities is to set the SMTP settings in your Web.config.  Here is a snippet you would put right above the system.web node:

<system.net>
    <mailSettings>
        <smtp from="service@website.com">
            <network host="mail.domain.com" port="25"
                     userName="..." password="..." />
        </smtp>
    </mailSettings>
</system.net>

Membership API and MembershipInfo Class

There is also a Membership API and an accompanying MembershipInfo class that you can call in order to retrieve and update user info from the database if you wanted to create your own custom controls or page logic. For instance, the following is code that I adapted from Part 11 of the tutorial I mentioned earlier in the introductory post of this series; this code activates an account when a user clicks the link emailed to them during registration:

public partial class Verify : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Make sure valid querystring value was passed
if (string.IsNullOrEmpty(Request.QueryString["ID"]) ||
!Regex.IsMatch(Request.QueryString["ID"],
@"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}"))
{
InformationLabel.Text = "An invalid ID value was passed " +
"in through the query string.";
}
else
{
//ID exists and is kosher, approve user
//Get the ID sent in on query string
Guid userId = new Guid(Request.QueryString["ID"]);

//Get user object
MembershipUser userInfo = Membership.GetUser(userId);

if (userInfo == null)
{
//Could not find user!
InformationLabel.Text = "The user account could not " +
"be found in the membership database.";
}
else
{
//User is valid, approve them
userInfo.IsApproved = true;
Membership.UpdateUser(userInfo);

//Display a message
InformationLabel.Text = "Your account has been " +
"verified and you can now log into the site.";
}
}
}
}

Read On!

Continue onward by reading the next blog post in this series found at the following link:

View Full Article

ASP.NET Providers - Getting Started

This blog post is part of a series about the ASP.NET Providers (namely Membership, Role Management, and Profile).  The introductory post in the series can be found at the following link, which introduces the Provider Model pattern and gives a personal example of an implementation I have been working on:

This post will deal with getting started using the ASP.NET Providers by setting up a database.

Database Setup

First, you will need to configure a database to securely store all of the site's user data and activity info.  You'll most likely be content with the already provided SQL Providers (such as the SqlMembershipProvider), but Microsoft also provides you with other options in many cases.  For example in the case of Membership, you also have the option of having your site use the ActiveDirectoryMembershipProvider or you can even roll your own MembershipProvider.  The nice thing about using any of these Microsoft Providers is that they are already set up to store sensitive data like passwords in an encrypted format in the database.

There are two tools you can use to automatically generate the necessary database tables needed for the SQL implementation.  The first tool is a web-based configuration tool launched from Visual Studio called the ASP.NET Website Administration Tool. It can not only create the database tables, but can also configure authorization rules, user roles, user accounts, and many other settings that go right into your Web.config.  It is launched by selecting the ASP.NET Configuration menu option in the Project menu (or Website menu, depending on which version of Visual Studio you have or the project template you selected).  However, this tool will create the database in a SQL Server file named ASPNETDB.mdf placed in the site's App_Data folder.  If you would prefer to create the database schema in an already existing install of SQL Server (likely on a different box), you need to use the aspnet_regsql.exe command-line tool.  The command-line tool's graphical interface can be launched by typing the name of the executable in a Visual Studio Command Prompt (located in the Start Menu under Visual Studio | Visual Studio Tools).

The only other thing you need now is the connection string to this newly populated database.  I will show you where in your Web.config to put the connection string in the next post of this series.

Read On!

Continue onward by reading the next blog post in this series found at the following link:

View Full Article

ASP.NET Providers - Membership, Role, and Profile

Seems like any website you start nowadays involves creating the same common features we see all over the web.  These include creating user account functionality, storing profile information, implementing role-based access to content and features, instantiating SQL tables and data access repositories, and so on, so forth.  In most cases it would be a complete waste of time and money to roll your own implementation every time.

There are plenty of frameworks out there that tackle this problem for you and abstract out details you shouldn't have to worry about.  If you are in the .NET world, there are a set of these services available to you that are baked right into the .NET 2.0 Framework.  I'm going to show you a personal example of how easy it is to add some of this functionality to an existing site, even one with an antique and cumbersome architecture.  Implementing these features using the ASP.NET 2.0 Provider Model on said architecture has convinced me that it couldn't be easier to add such functionality to a website, no matter what beast of a site you are dealing with.

ASP.NET 2.0 Provider Model

With the advent of ASP.NET 2.0, Microsoft introduced a set of configuration-driven services that adhere to the Provider Model pattern.  These services focus on storing application state of a website using a very flexible and extensible data access strategy.  The available features that can be added to your website include Membership (which includes authentication and authorization), Role Management, Profile, Session State, Web Parts Personalization, and Site Map navigation.  The whole idea is to be able to secure and enhance an existing site by dropping in a few lines into the Web.config, using a Microsoft utility to automatically create database tables (most likely your chosen storage medium), and then dropping, configuring, and skinning a few controls into your existing pages.  To read a more thorough introduction to the Provider Model and these ASP.NET 2.0 Provider services (including a few helpful diagrams), check out the following link:

Personal Example

We currently maintain a series of desktop products that we have been entrusted with.  Under the covers, these "desktop" products were originally written in Java as locally-hosted websites using Apache's web server.  In order to be compatible with Windows Vista, we have since ported these products to .NET 2.0 and currently use UltiDev's free, light-weight, and redistributable web server named Cassini (essentially the same thing as the development web server found in Visual Studio and a great alternative to IIS).  Many of the features are implemented in JavaScript and the content is almost entirely static HTML pages.  There were only a few Java Servlets that we ported to .NET HTTP Handlers and any database storage has been done using Microsoft Access databases.  This set of products also has other interaction requirements like the ability to view content from another product while staying in the context of the currently open product.  Finally, the installers for a few of these desktop products are getting to be nearly 600 MB in size, which has perpetuated the need for distributing the products to the users offline.

We are in the process right now of exploring the cost benefits and customer experience improvements in moving this set of offerings to an online suite of websites.  The first step we are taking is to build an online version of one of the products where users can obtain a user account to view the content.  Building new applications is one thing, but upgrading and maintaining existing applications (especially ones you have inherited) is a whole different development experience.  This is where my appreciation for the ease and flexibility of what Microsoft is offering comes into play.

Read On!

The rest of the blog posts in this series can be found at the following links:

In addition, I came across an issue when using the Profile system with the Web Application project template instead of the Web Site project template as found in Visual Studio's default set of project templates.  It has to do with the Profile proxy class object not being auto-generated by Visual Studio when using the Web Application project template.  Read the following blog post for a discussion of the problem and it's solution:

Also, I have another post discussing the advantages of using the ASP.NET Provider system under IIS 7 found in Windows Vista and Server 2008; it will also include some issues with using this system if some of your content is static HTML instead of ASPX pages.  You can find all of this goodness by following the link below:

Finally, I based my implementation on a 13-part tutorial series by Scott Mitchell on 4GuysFromRolla.com, starting at this link:

Enjoy!

View Full Article