0844 244 8080

How to Override ASP.NET's Generate Password function to create easier, more friendly passwords

by Paul Freeman-Powell

Share |

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 your web.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! :-)



Share |
Paul Freeman-Powell

Paul Freeman-Powell is a technology, software and hardware enthusiast. He founded and owns caeus.com Ltd. and works as a web developer, IT consultant and computer repair technician. In his spare time, he speaks French and Spanish fluently and is also a keen drummer and photographer (but not at the same time). His personal web site can be found at www.paulfp.net.

 

Your Comments

CAPTCHA Authorisation Code

Comments are publicly viewable so please don't include any personal data such as your phone number or email address. Submitting a comment indicates acceptance of our Terms & Conditions.

1. At 11:34 on 7 Mar 2012 Lois wrote:

Hazel thanks for your note. (LOVE The Sartorialist!!). All black is often the default colour because it's the easier to unify (imagine an ensemble full of slightly different shades of red), it's easy on the eyes, and the audience tends to focus more on the music than if the ensemble were wearing different colours. The problem with saying go for it, wear any colour is what one person considers stylish another will consider completely inappropriate. There there's the issue of colour clashing. And in classical music, there are known stereotypes about what kind of dress is associated with certain types of music. Opera performers (and audiences) tend to go all out with style and flamboyance; Baroque performers (and audiences) tend not to consider fashion a big deal and are very low-key with their apparel. Ultimately, no, I don't think ensembles should be able to wear any colour; then it looks like a rehearsal.

2. At 01:08 on 8 Mar 2012 Fannie wrote:

Liz is not just ANY page turner. Liz is the Heifetz, the Pavarotti, the veritable Yo-Yo Ma of page turners. She is the kind of page turned who, if I was completely fumbling a difficult passage, would suddenly have an uncontrollable puking fit so as to draw attention away from my screwup. She also knows exactly how many pieces of sushi you might need at intermission. At least that's my experience; your mileage may vary One last bit of clothing advice for page turners: No dangly loose jackets. I once played a whole violin recital with silk caressing my left cheek at every turn. I'm not saying I didn't enjoy it, but it was kind of distracting.

3. At 09:51 on 8 Mar 2012 Pait wrote:

Paki, aunque con retraso, te comunico que todos los que lo solicist teis a trav s de los coemntarios est is admitidos/as

4. At 01:41 on 14 Mar 2012 Jahlin wrote:

Paki, aunque con retraso, te comunico que todos los que lo solicist teis a trav s de los coemntarios est is admitidos/as

5. At 02:01 on 16 Mar 2012 Cassara wrote:

Paki, aunque con retraso, te comunico que todos los que lo solicist teis a trav s de los coemntarios est is admitidos/as

Copyright © caeus.com Ltd. 2011. This article and all its contents are the property of caeus.com Limited and are protected by copyright. You may not distribute, modify, transmit, reuse, repost, or use the content of this article for public or commercial purposes (including text and images) without written permission from caeus.com Limited. The views expressed in this article and sites linked to herein are solely those of the author or individual(s) providing them and do not reflect the opinions of caeus.com Ltd., its parents, affiliates or subsidies. Any trademarks and brands mentioned in this article are the property of their respective owners and their use does not imply any affiliation with, or endorsement by, caeus.com Limited. The content of this article is provided in good faith and for information purposes only; you follow any advice given entirely at your own risk and no responsibility can be taken for any consequences which may arise as a result of following advice given in this article.

Articles & How-To Guides


Sign up to caeus.com
Secure Data Destruction... click here

 

Connect With Us:

Valid CSS! Valid XHTML 1.1!