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






4.82/5 (4 votes)
Sample code on how to integrate the Password Strength Indicator using jQuery and XML plug-in with ASP.NET MVC3 Razor.
- Watch this script in action - demo
- Download Source (MVC3) - 2.4 MB
- Download Source (MVC2) - 350.6 KB New
- Download latest version of source code (external link)
Table of contents
- Introduction
- Getting Started
- Changes in Account Model
- Changes in Account Controller
- Changes in Account Registration View
- Conclusion
- History
- Resources
- Demo
- Download
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
- Create a new project
- Get the latest version of the plug-in and copy the jquery.password-strength.js into the Scripts folder
- Copy the XML folder into the project root or place it into Content folder
- Create the PasswordSetting class under the Models folder
- The files that we’re going to modify are AccountController.cs, AccountModels.cs, Register.cshtml and ChangePassword.cshtml
- 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
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