Click here to Skip to main content
15,886,038 members
Articles / Web Development / ASP.NET

ASP.NET MVC3 - Password Strength Indicator using jQuery and XML

Rate me:
Please Sign up or sign in to vote.
4.82/5 (4 votes)
12 Sep 2012CPOL4 min read 39.9K   898   14   4
Sample code on how to integrate the Password Strength Indicator using jQuery and XML plug-in with ASP.NET MVC3 Razor.

Table of contents

Introduction

The purpose of this article is to demonstrate on how to integrate Password Strength Indicator using jQuery and XML plug-in with ASP.NET MVC 3 Razor. In this tutorial, we will include the plug-in into the Register Account and Change Password views.

Getting Started

Shown below is the content of the sample application. In Visual Studio 2010

  1. Create a new project
  2. Get the latest version of the plug-in and copy the jquery.password-strength.js into the Scripts folder
  3. Copy the XML folder into the project root or place it into Content folder
  4. Create the PasswordSetting class under the Models folder
  5. The files that we’re going to modify are AccountController.cs, AccountModels.cs, Register.cshtml and ChangePassword.cshtml
  6. Please note that the absolute link to the XML file in the jquery.password-strength.js is hardcoded to localhost. Make sure you modify it accordingly before deploy it to production.

Figure 1
solution

Changes in Account Model

In the RegisterModel class, remove the StringLength attribute from the Password property because the length will be checked by the plug-in. If we leave it there, it will display both the error message and the password strength indicator bar until we hit the six characters.

Listing 1

public class RegisterModel
    {
        [Required]
       // [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }
    }

Changes in Account Controller

In this version, we will use LINQ to read the XML file. The GetPasswordRegex() method in this controller is responsible to retrieve the password information from the XML file and store it in the PasswordSetting object. Then it will use the information to put together the password strength regular expression. For this demo, the path to the XML file is hardcoded, you can place the path to the XML file in the web.config.

Listing 2

internal string GetPasswordRegex()
{
    XDocument xmlDoc = XDocument.Load(Request.MapPath("~/xml/PasswordPolicy.xml"));

    var passwordSetting = (from p in xmlDoc.Descendants("Password")
                            select new PasswordSetting
                            {
                                Duration = int.Parse(p.Element("duration").Value),
                                MinLength = int.Parse(p.Element("minLength").Value),
                                MaxLength = int.Parse(p.Element("maxLength").Value),
                                NumsLength = int.Parse(p.Element("numsLength").Value),
                                SpecialLength = int.Parse(p.Element("specialLength").Value),
                                UpperLength = int.Parse(p.Element("upperLength").Value),
                                SpecialChars = p.Element("specialChars").Value
                            }).First();

    StringBuilder sbPasswordRegx = new StringBuilder(string.Empty);
    //min and max
    sbPasswordRegx.Append(@"(?=^.{" + passwordSetting.MinLength + "," + passwordSetting.MaxLength + "}$)");

    //numbers length
    sbPasswordRegx.Append(@"(?=(?:.*?\d){" + passwordSetting.NumsLength + "})");

    //a-z characters
    sbPasswordRegx.Append(@"(?=.*[a-z])");

    //A-Z length
    sbPasswordRegx.Append(@"(?=(?:.*?[A-Z]){" + passwordSetting.UpperLength + "})");

    //special characters length
    sbPasswordRegx.Append(@"(?=(?:.*?[" + passwordSetting.SpecialChars + "]){" + passwordSetting.SpecialLength + "})");

    //(?!.*\s) - no spaces
    //[0-9a-zA-Z!@#$%*()_+^&] -- valid characters
    sbPasswordRegx.Append(@"(?!.*\s)[0-9a-zA-Z" + passwordSetting.SpecialChars + "]*$");

    return sbPasswordRegx.ToString();
}

Add the code in Listing 3 to the beginning of the Register method. During testing with JavaScript disabled, I found that the error "System.ArgumentNullException: Value cannot be null. Parameter name: input" will occur when the Password input is empty. In order to avoid that, make sure the Password input is not empty before calling the Regex.IsMatch method. If the password does not meet the policy, display “Password does not meet policy!” error message on the screen.

Listing 3

if (!string.IsNullOrEmpty(model.Password))
    {
        if (!Regex.IsMatch(model.Password, GetPasswordRegex()))
        {
            ModelState.AddModelError("Password", "Password does not meet policy!");
        }
    }

Changes in Account Registration View

Include a reference to the jquery.password-strength.js plug-in on the page and add the script in listing 6 to the bottom of the view. Add a password policy link under the password textbox and set it ID to "passwordPolicy". Refer to listing 4.

Listing 4

@Html.ActionLink("Password policy","", null, new { id = "passwordPolicy" })

Initially, the only codes under the button submit click function was in listing 5. For some reason, the client side validation for the whole form was not working on button submit click. Which does make sense because the plug-in should return false if user click on the submit button without any input in the password textbox. But the same set of code works fine on the ASP.NET application. The work around is to manually invoke the jQuery valid() function to checks whether all the form elements are valid before checking if the password meet requirement.

Listing 5

$("[id='btnSubmit']").click(function () {
     return myPlugin.metReq(); //return true or false
});

Listing 6

<script type="text/javascript">
    $(document).ready(function () {
        var myPlugin = $("input[id='Password']").password_strength();

        $("[id='btnSubmit']").click(function () {
            var $form = $('form');
            if ($form.valid()) {
                return myPlugin.metReq(); //return true or false
            }
        });

        $("[id='passwordPolicy']").click(function (event) {
            var width = 350, height = 300, left = (screen.width / 2) - (width / 2),
            top = (screen.height / 2) - (height / 2);
            window.open("http://localhost:1234/xml/PasswordPolicy.xml", 'Password_poplicy',
	    'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top);
            event.preventDefault();
            return false;
        });
    });
</script>

Conclusion

The plug-in also implemented in the change password view in this sample. Again, I would recommend using absolute URL to your XML file and download the demo and explore it in order to grasp the full concept of it because I might miss some important information in this article. I hope someone will find this information useful and make your programming job easier. If you find any bugs or disagree with the contents or want to help improve this article, please drop me a line and I'll work with you to correct it. Please send me an email if you want to help improve this article.

History

07/29/2012 – First Release (v01.00.00)
09/13/2012 – Added demo project using ASP.NET MVC2 (v01.01.00)

Resources

http://stackoverflow.com/questions/5127813/call-mvc-3-client-side-validation-manually-for-ajax-posts

Demo

http://mvc.ysatech.com/Account/Register

Download

http://download.ysatech.com/MvcPasswordStrength.zip

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
I have over 10 years of experience working with Microsoft technologies. I have earned my Microsoft Certified Technology Specialist (MCTS) certification. I'm a highly motivated self-starter with an aptitude for learning new skills quickly.

Comments and Discussions

 
BugDisplaying "At leas", truncating last letter from status Pin
Member 108046528-May-14 6:11
Member 108046528-May-14 6:11 
GeneralMy vote of 5 Pin
Tbone198313-Sep-12 5:04
Tbone198313-Sep-12 5:04 
QuestionGreat Pin
Albarhami13-Sep-12 3:28
Albarhami13-Sep-12 3:28 
GeneralMy vote of 3 Pin
Albarhami13-Sep-12 3:28
Albarhami13-Sep-12 3:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.