Skip to main content

One of the great advantages of using the ASP.NET platform for web development is its wide range of built-in functions and web controls, which mean that you can create a very feature-rich web application in a breeze. However, in my opinion this do-everything-for-you approach can ironically also be one of ASP.NET’s major weaknesses, and a great example of this is the built-in GeneratePassword() function.

Microsoft have given web developers a certain amount of control over the complexity of the passwords generated – eg., you can specify the minimum length and the minimum number of non-alphanumeric characters it contains. But that’s all you really can specify – the minimum number of non-alphanumeric characters. You can’t specify a maximum and you can’t tell it to have none!

That means that when a user forgets his or her password to your ASP.NET web site, they’re likely to be given a new password along the lines of: bS8xh&^2|3*ohg. Clearly, it’s a good idea to have a secure password (click the link to test yours now!) and it’s only ever intended to be a temporary password anyway, but as far as complex passwords go that’s fairly high up there. Us computery types wouldn’t have a problem with that at all, as we’d just copy and paste it into the login form and be away but in the real-world most users simply can’t cope with this level of complexity, and companies’ technical support teams end up wasting large amounts of time answering phone calls and support tickets from users having difficulties. (Try explaining to a non-programmer where to find the ¬ or | keys on the keyboard, and you’ll know what I mean…)

So, in this article I’m going to show you how to override just the part of ASP.NET that’s responsible for actually generating a new random password, whilst still taking advantage of the built-in functionality which actually changes the user’s password in our database, etc. Using this method we can change just the bit we need to change without having to reinvent the wheel and rewrite the whole feature.

Note: this tutorial uses C# as the main programming language. If you’re using VB.NET, check out Developer Fusion’s excellent C# to VB.NET conversion tool.

Step 1: Create a New Class

The first step is to create a new class for our own code to live in. Create the file ExtSQLMembershipProvider.cs and place it in your App_Code folder. Inside that file, copy and paste this code:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Data;

using System.Data.SqlClient;

 

public class MyMembershipProvider :

 

    System.Web.Security.SqlMembershipProvider

 

{

 

    public string GeneratedPassword;

 

    public MyMembershipProvider()

 

        : base()

 

    {

 

    }

 

    public override string GeneratePassword()

 

    {

        Random random = new Random();

 

        int randomNumber = random.Next(100, 10000);

 

        string NewRandomPassword = “”;

        SqlCommand cmd = null;

        SqlDataReader rdr = null;

 

        System.Data.SqlClient.SqlConnection conn =

        new System.Data.SqlClient.SqlConnection();

        conn.ConnectionString =

         “Data Source={ip-address};Initial Catalog={table};User ID={YourID};Password={password}”;

        try

        {

            conn.Open();

 

            string CommandText = “SELECT TOP 1 word FROM words ORDER BY NEWID()”;

            cmd = new SqlCommand(CommandText);

            cmd.Connection = conn;

 

            rdr = cmd.ExecuteReader();

 

            while (rdr.Read())

            {

                NewRandomPassword = rdr[“word”].ToString() + randomNumber;

            }

 

            return NewRandomPassword;

        }

        catch (Exception ex)

        {

           string FailSafeNewPassword = “new” + randomNumber + “password”;

           return FailSafeNewPassword;

        }

        finally

        {

            conn.Close();

        }

 

    }

 

}

Basically, we create a new function, GeneratePassword(), which overrides the built-in function of the same name and it’s in here that we put our code.

It’s up to you how you create your new passwords but the approach I have gone for is to have a randomly-selected word from the English language (note the SQL query which achieves this) and then put a random set of digits after it. The random digits mean that it doesn’t matter if two people get the same word as their password, as it’s incredibly unlikely that they’d also get the same number.

For this to work, I created a new table in the database called words. In this database I have an ID and a word column, with around 60,000 fields all containing different English words. To find something similar, just Google “list of English words” or something similar and you’ll be able to create your own fairly easily.

Note: you may, as I did, have to spend some time removing rude, offensive or generally inappropriate words from your wordlist. The last thing you want is to offend your users!

You’ll see as well that I’ve allowed for a scenario where the script cannot connect to your database for whatever reason. In this case, there should (hopefully!) be no reason why the random number generator would fail also, so I’ve created a “failsafe” password which contains the words “new” and “password” separated by a random number. That way, if word got around that your web site’s Forgotten Password feature was done, no-one would be able to take advantage of it by resetting other folks’ passwords and knowing what they’d be reset to, as it still contains a random element.

Step 2: Modify Your PasswordReset.aspx Page

Next, we need to make sure that the web control on your page is using the correct membership class. Make sure your code looks something like mine:

<asp:PasswordRecovery 

  ID=”PasswordRecovery1″

  runat=”server”

  MembershipProvider=”AspNetSqlMembershipProvider”

  OnSendingMail=”PasswordRecovery1_SendingMail”>

 

<MailDefinition

  From=”registrations@your-superb-website.com”

  BodyFileName=”~/EmailTemplates/ResetPassword.htm”

  IsBodyHtml=”true”

  Subject=”Your New Password”>

</MailDefinition>

Notice here that I’ve also overridden the very basic and boring email that ASP.NET sends out by detault, to include a template I’ve written myself. This can be richly formatted with HTML and CSS to include hyperlinks, backgrounds and your web site logo. The important bit you need to include in that is this:

<p>These are your new details:</p>

<table>

<tr>

<td><b>Username:</b></td><td><%UserName%></td>

</tr>

<tr>

<td><b>Password:</b></td><td><%Password%></td>

</tr>

</table>

Step 3: Update your web.config file

Finally, we need to configure your web site to use our new membership class as well (containing our own code to generate the password) rather than just the built-in ASP.NET one. Make sure you have this in yourweb.config file:

    <membership userIsOnlineTimeWindow=”30″>

      <providers>

      <remove name=”AspNetSqlMembershipProvider” />

 

<add name=”AspNetSqlMembershipProvider” 

type=”MyMembershipProvider” 

connectionStringName=”LocalSqlServer” 

enablePasswordRetrieval=”false” 

enablePasswordReset=”true” 

requiresQuestionAndAnswer=”false” 

passwordFormat=”Hashed” 

minRequiredPasswordLength=”5″ 

minRequiredNonalphanumericCharacters=”0″

requiresUniqueEmail=”false” 

applicationName=”/” 

maxInvalidPasswordAttempts=”10″ />

 

      </providers>

    </membership>

To be on the safe side, I’d recommend that you comment out the existing settings rather than deleting them outright, just in case you have any problems or make a mistake. In general, make sure you backup your web site before making any changes, and if possible test it all out on a development server before making it live for the world to see!

Conclusion

So there we have it, in a few simple steps we’ve greatly reduced the number of support calls that your company is likely to receive due to customers having problems logging in to the web site. The passwords we generate are still secure as they contain a random word and then a random number, and we encourage members to change the password as soon as they log in anyway.

Further development

To make the passwords even more secure, why not modify the C# code to randomise whether each character in the chosen word is in lower or upper case? Be careful though – depending on your web site’s audience this may also cause confusion and you don’t want to end up defeating the object of the whole exercise!

I hope this article has been useful to you – if you’ve implemented this in your web site then please feel free to comment below and leave a web address too, and don’t forget to share this article on Facebook and Twitter! 🙂

Paul Freeman-Powell

Paul (@paulfp) is the main presenter of the award-winning Switched On Network YouTube Channel, which covers a variety of interesting topics usually relating to his love of technology and all things geeky. He also founded and runs Innobella Media, where he leads in all aspects of video production, video editing, sound & lighting. A father of 3 children including twins, his hobbies used to include photography, playing the drums and cycling. With a degree in Modern European Languages, Paul speaks French, Spanish and a little bit of Italian, and holds dual British & Irish citizenship.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Close Menu
Freelance Camera Operator, Videographer, Vision Mixer, Sound Engineer, Video/Audio Editor & Photographer