The benefits of using Microsoft's new Membership Provider, and an explanation of how to configure and use them, are well documented on MSDN (http://msdn2.microsoft.com/en-us/library/yh26yfzy(VS.80).aspx). Certainly the Sql Membership Provider, in conjunction with the suite .Net controls, does a great job providing everything needed for creating and managing user accounts for a common web application. But sometimes your needs may be a little outside of what can be configured or coded using the Provider as is. Fortunately, extending the provider is a very straightforward task.
I recently implemented a .Net 2.0 website using many of the providers, including Membership, Role, and Profile. While the Membership Provider gave us industry standard security "for free", the requirements dictated that a few features needed to be changed. One of those features was the passwords that are automatically created when using the Password Reset button. By default, the provider creates a string of characters that is long and contains non-alphanumeric values. Even cutting and pasting these into the browser becomes difficult (not to mention confusing) when the first character of your new password is a ":" (colon). My requirements called for a simple string of letters and numbers, preferably 10 characters in length. Despite the numerous configuration options available, this functionality was nowhere to be found.
The solution involved creating a CustomSqlMembershipProvider class that inherited from the existing SqlMembershipProvider to do most of the heavy lifting.
Below is the code that provides configurable length Password Reset function that contains only numbers and lowercase letters, leaving out ambiguous characters to avoid confusion.
Some things to note...
- Inherit from SqlMembershipProvider to gain access to the base implementation.
- Read any custom config entries in the Initialize override method, but be sure to remove those entries as the base provider will not recognize them and will throw an exception.
- Be sure to call base.Initialize to trigger the default implementation.
Hope this helps!
public class MembershipProvider : SqlMembershipProvider
{
System.Random rnd;
string[] characters;
const int DefaultResetPasswordLength = 10;
private int ResetPasswordLength;
public MembershipProvider()
{
rnd = new Random();
characters = FillCharacters();
}
public override void Initialize(string name,
System.Collections.Specialized.NameValueCollection config)
{
ResetPasswordLength = DefaultResetPasswordLength;
string ResetPasswordLengthConfig = config["resetPasswordLength"];
if (ResetPasswordLengthConfig != null)
{
// Have to remove the config entry as the provider we are
// inheriting from doesn't understand it and will throw an
// exception
config.Remove("resetPasswordLength");
if (!int.TryParse(ResetPasswordLengthConfig,
out ResetPasswordLength))
{
// Have to reset to default as TryParse will set it to 0
// if the value can't be parsed
ResetPasswordLength = DefaultResetPasswordLength;
}
}
base.Initialize(name, config);
}
// Create a more user friendly password to avoid confusion when
// trying to key in the new value
public override string GeneratePassword()
{
string newPassword = string.Empty;
for (int i = 0; i < ResetPasswordLength; i++)
{
newPassword += GetRandomAlphaNumericCharacter();
}
return newPassword;
}
/// <summary>
/// Create an array of characters to user for password reset.
/// Exclude confusing or ambiguous characters such as 1 0 l o i
/// </summary>
/// <returns></returns>
private string[] FillCharacters()
{
string[] characters = new string[31];
characters[0] = "2";
characters[1] = "3";
characters[2] = "4";
characters[3] = "5";
characters[4] = "6";
characters[5] = "7";
characters[6] = "8";
characters[7] = "9";
characters[8] = "a";
characters[9] = "b";
characters[10] = "c";
characters[11] = "d";
characters[12] = "e";
characters[13] = "f";
characters[14] = "g";
characters[15] = "h";
characters[16] = "j";
characters[17] = "k";
characters[18] = "m";
characters[19] = "n";
characters[20] = "p";
characters[21] = "q";
characters[22] = "r";
characters[23] = "s";
characters[24] = "t";
characters[25] = "u";
characters[26] = "v";
characters[27] = "w";
characters[28] = "x";
characters[29] = "y";
characters[30] = "z";
return characters;
}
private string GetRandomAlphaNumericCharacter()
{
return characters[rnd.Next(characters.GetUpperBound(0))];
}
}
No comments:
Post a Comment