未加星标

Password Strength Meter in AngularJS 1.x

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二04 | 时间 2017 | 作者 红领巾 ] 0人收藏点击收藏
Free Course Getting Started with Angular 2

Angular 2 is the shiny new framework that comes with a lot of new concepts. Learn all the great new features.

Code Demo

In this tutorial, we would be creating a simple registration form with just fields for fullname, email and password. We would use zxcvbn to estimate the strength of the password in the form and also provide a visual feedback. We would also use AngularJS for effortless two-way data bindings.

At the end of the tutorial, the final page will behave as shown in the following live demo:

Why measure Password Strength?

Passwords are commonly used for user authentication in most web applications and as such, it is required that passwords be stored in a safe way. Over the years, techniques such as one-way password hashing - which involves salting most of the times, have been employed to hide the real representation of passwords being stored in a database.

Although password hashing is a great step in securing password, the user still poses a major challenge to password security. A user who uses a very common word as password makes the effort of hashing fruitless, since a bruteforce attack can crack such password in a very short time. Infact, if highly sophisticated infrastructure is used for the attack, it may even take split milliseconds, depending on the password complexity or length.

Many web applications today such as Google, Twitter, Dropbox, etc insist on users having considerably strong passwords either by ensuring a minimum password length or some combination of alphanumeric characters and maybe symbols in the password.

How then is password strength measured?Dropbox developed an algorithm for a realistic password strength estimator inspired by password crackers. This algorithm is packaged in a javascript library called zxcvbn . In addition, the package contains a dictionary of commonly used English words, names and passwords.

Getting Started

Before we begin the tutorial, we would download all the dependencies we need using the Bower package manager. If you don't already have Bower in your system, you can follow the Bower Installation Guide . Run the following command to install all the dependencies for the tutorial.

bower install zxcvbn angularjs#1.5.9 bootstrap The root folder should contain two folders and one file. assets folder bower_components folder index.html file

The folder structure for our project should look like the following screenshot - you can create the folders and directories as required.


Password Strength Meter in AngularJS 1.x
Starting-off with the HTML

Let's begin by adding the basic markup for our page in the index.html file. We would link to the Bootstrap files - bootstrap.min.css and bootstrap-theme.min.css , and also the angular.min.js framework from our bower_components folder. We would also link to our project's css and js files in the assets folder. See the following code for the basic HTML markup of our page.

<!-- index.html --> <!DOCTYPE html> <html class="no-js"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Password Strength</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap-theme.min.css"> <link rel="stylesheet" href="assets/css/main.css"> </head> <body> <div class="main-container"> <div class="form-container"> <form action="" method="POST" role="form"> <legend class="form-label">Join the Team</legend> <div class="form-group"> <label for="fullname">Fullname</label> <input type="text" class="form-control" id="fullname" placeholder="Enter Fullname"> </div> <div class="form-group"> <label for="email">Email</label> <input type="email" class="form-control" id="email" placeholder="Enter Email Address"> </div> <div class="form-group"> <label for="password">Password</label> <div class="form-hint">To conform with our Strong Password policy, you are required to use a sufficiently strong password. Password must be more than 7 characters.</div> <input type="password" class="form-control" id="password" placeholder="Enter Password"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> </div> <script src="bower_components/angular/angular.min.js"></script> <script src="assets/js/app.js"></script> </body> </html>

At this point, our page should look like the following screenshot:


Password Strength Meter in AngularJS 1.x
Spicing-up the page with CSS

Now we would add some CSS rules to the assets/css/main.css file to spice up the page.

/* main.css */ body { margin: 0; padding: 0; } .main-container { display: table; width: 400px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; } .form-container { position: relative; bottom: 100px; display: table-cell; vertical-align: middle; } .form-container form > div { padding: 0 15px; } .form-container form > button { margin-left: 15px; } legend.form-label { font-size: 24pt; padding: 0 15px; } .form-hint { font-size: 7pt; line-height: 9pt; margin: -5px auto 5px; color: #999; }

At this point, our page should look like the following screenshot:


Password Strength Meter in AngularJS 1.x
Loading zxcvbn asynchronously

Now we would asynchronously load the zxcvbn package into our page. We would add the script in the assets/js/app.js file. The following script programmatically creates a new <script> element that is inserted before the first script element defined in the page, when the page is finished loading. The src of this script element points to the zxcvbn.js file. The async attribute is also set to true to enable asynchronous loading.

/* app.js */ (function() { var ZXCVBN_SRC = 'bower_components/zxcvbn/dist/zxcvbn.js'; var async_load = function() { var first, s; // create a <script> element using the DOM API s = document.createElement('script'); // set attributes on the script element s.src = ZXCVBN_SRC; s.type = 'text/javascript'; s.async = true; // html5 async attribute // Get the first script element in the document first = document.getElementsByTagName('script')[0]; // insert the <script> element before the first in the document return first.parentNode.insertBefore(s, first); }; // attach async_load as callback to the window load event if (window.attachEvent != null) { window.attachEvent('onload', async_load); } else { window.addEventListener('load', async_load, false); } }).call(this);

Now we can try using the zxcvbn() function with any password string from our browser's console. The zxcvbn() function returns a result object with several properties. In this tutorial, we would be concerned only with the score property, which is an integer from 0 - 4 (useful for implementing a strength bar).

0 - too guessable 1 - very guessable 2 - somewhat guessable 3 - safely unguessable 4 - very unguessable console.log(zxcvbn('password'));

See the following video on testing the zxcvbn() method on the browser's console.

Mixing-in some AngularJS

Now we would make some little improvements to our code to engage AngularJS. First let's create a module for our app called PasswordStrength , and a simple controller for our form called FormController . We would append the following script to the assets/js/app.js file.

// creating the app module angular.module('PasswordStrength', []); // adding a controller to the module angular.module('PasswordStrength').controller('FormController', function($scope) {});

Next, we would edit our index.html file to add an ng-app directive for the module on the root <html> element, and an ng-controller directive for the controller on the <form> element.

<!-- adding the ng-app directive --> <html class="no-js" ng-app="PasswordStrength"> <!-- adding the ng-controller directive --> <form action="" method="POST" role="form" ng-controller="FormController"> Validating the Form

Now we can add our validation logic to the form.

First, we would give names to the form and the input fields, and also add ng-model directives to the input fields to be able to harness the built-in NgModelController . Next, we would add the ng-required constraint to the input fields, since we desire they should be filled. Next, we would disable the submit button using the ng-disabled directive and only enable it when the form is fully validated. Finally, we would harness the ng-class and ng-show directives to provide error feedback and messages for the input elements.

The modified form in our index.html file should look like this:

<form action="" method="POST" name="joinTeamForm" role="form" ng-controller="FormController"> <legend class="form-label">Join the Team</legend> <div class="form-group"> <label for="fullname">Fullname</label> <div class="error form-hint" ng-show="joinTeamForm.fullname.$dirty && joinTeamForm.fullname.$error.required" ng-cloak>{{"This field is required."}}</div> <input type="text" class="form-control" ng-class="(joinTeamForm.fullname.$dirty && joinTeamForm.fullname.$invalid) ? 'error' : ''" id="fullname" name="fullname" placeholder="Enter Fullname" ng-required="true" ng-model="fullname"> </div> <div class="form-group"> <label for="email">Email</label> <div class="error form-hint" ng-show="joinTeamForm.email.$dirty && joinTeamForm.email.$error.required" ng-cloak>{{"This field is required."}}</div> <div class="error form-hint" ng-show="joinTeamForm.email.$dirty && joinTeamForm.email.$error.email" ng-cloak>{{"Email is invalid."}}</div> <input type="email" class="form-control" ng-class="(joinTeamForm.email.$dirty && joinTeamForm.email.$invalid) ? 'error' : ''" id="email" name="email" placeholder="Enter Email Address" ng-required="true" ng-model="email"> </div> <div class="form-group"> <label for="password">Password</label> <div class="form-hint">To conform with our Strong Password policy, you are required to use a sufficiently strong password. Password must be more than 7 characters.</div> <input type="password" class="form-control" ng-class="(joinTeamForm.password.$dirty && joinTeamForm.password.$invalid) ? 'error' : ''" id="password" name="password" placeholder="Enter Password" ng-required="true" ng-model="password"> </div> <button type="submit" class="btn btn-primary" ng-disabled="joinTeamForm.$invalid">Submit</button> </form>

In the preceeding code, we have named our form as joinTeamForm and have given names to the input elements making it possible for us to harness Angular's built-in NgModelController . We have also created data-bindings for the input elements using the ng-model directive.

We used some of the validation state properties - $dirty , $invalid , $error , provided by the NgModelController API to determine if our form is fully validated. The ng-class directive was also used to dynamically add an error class to the input elements based on the validation criteria.

Also, we used ng-cloak to prevent the browser from showing our error messages while rendering. Since, we included angular.js at the end of our page, this would not be effective. To correct this, we would add the following CSS rule to the main.css file.

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; }

Now, we would add some CSS rules to the main.css file for our error feedback.

.form-control.error { border-color: red; } .form-hint.error { color: #C00; font-weight: bold; font-size: 8pt; }

At this point, our page should look like the following screenshot - observe that the form submit button is now disabled on page load.


Password Strength Meter in AngularJS 1.x
Adding the Password Strength Meter

Now we would go ahead to create the password strength meter. We would also create a new directive in our module called okPassword , that will define a custom validation constraint for the password element, which will ensure that a valid password must be more than 7 characters and must have a minimum zxcvbn score of 2 . We will also add a visual feedback to keep track of the password length.

First, let's add the following into our index.html file, immediately after the password field element, for our password strength meter.

<div class="label password-count" ng-class="password.length > 7 ? 'label-success' : 'label-danger'" ng-cloak>{{ password | passwordCount:7 }}</div> <div class="strength-meter"> <div class="strength-meter-fill" data-strength="{{passwordStrength}}"></div> </div>

Here, we are using the ng-class directive and Bootstrap's label classes to provide feedback based on the password length. We are also using a custom passwordCount filter to slightly format the display of the password length.

Also, we are binding the value for the data-strength attribute to the passwordStrength property of the controller's scope, which will contain the password strength score.

Now, let's add the following css rules to the main.css file to style the password strength meter which we just created.

.password-count { float: right; position: relative; bottom: 24px; right: 10px; } .strength-meter { position: relative; height: 3px; background: #DDD; margin: 10px auto 20px; border-radius: 3px; } .strength-meter:before, .strength-meter:after { content: ''; height: inherit; background: transparent; display: block; border-color: #FFF; border-style: solid; border-width: 0 5px 0 5px; position: absolute; width: 80px; z-index: 10; } .strength-meter:before { left: 70px; } .strength-meter:after { right: 70px; } .strength-meter-fill { background: transparent; height: inherit; position: absolute; width: 0; border-radius: inherit; transition: width 0.5s ease-in-out, background 0.25s; } .strength-meter-fill[data-strength='0'] { background: darkred; width: 20%; } .strength-meter-fill[data-strength='1'] { background: orangered; width: 40%; } .strength-meter-fill[data-strength='2'] { background: orange; width: 60%; } .strength-meter-fill[data-strength='3'] { background: yellowgreen; width: 80%; } .strength-meter-fill[data-strength='4'] { background: green; width: 100%; }

Here, we have made our password strength meter to indicate five levels for the different password strength scores ranging from 0 to 4 . We have also specified different colors and fill width for each score level.

At this point, our page should look like the following screenshot. Observe that the page exhibits some strange behaviour since we have not yet defined the passwordCount filter.


Password Strength Meter in AngularJS 1.x

Before we proceed, we would define the passwordCount filter which slightly formats the display of the password length in the view. Let's append the following to the app.js file to create the filter.

// creating the passwordCount filter angular.module('PasswordStrength').filter('passwordCount', [function() { return function(value, peak) { var value = angular.isString(value) ? value : '', peak = isFinite(peak) ? peak : 7; return value && (value.length > peak ? peak + '+' : value.length); }; }]);

In the preceeding code, the passwordCount filter takes a string value and an optional peak parameter which defaults to 7 if omitted or not a valid integer. If the length of the input string is less than the peak , it returns the length of the string; otherwise, it returns {peak}+ .

Now we can get visual feedback for our password length as we type. See the following screenshot:


Password Strength Meter in AngularJS 1.x

Now, we would go on to create the okPassword directive for the password field. We would also create a service that will encapsulate the implementation of the zxcvbn() function. Let's add the following to the app.js file to create the service.

// creating a service to provide zxcvbn() functionality angular.module('PasswordStrength').factory('zxcvbn', [function() { return { score: function() { var compute = zxcvbn.apply(null, arguments); return compute && compute.score; } }; }]);

Here, we have created a service called zxcvbn that provides just one API method score() . The score() method takes the same parameters as the zxcvbn() function and calls it internally. It returns the estimated password strength score.

Now, we can apply this service to create our directive. Add the following to the app.js file to create the directive.

// creating the okPassword directive with zxcvbn as dependency angular.module('PasswordStrength').directive('okPassword', ['zxcvbn', function(zxcvbn) { return { // restrict to only attribute and class restrict: 'AC', // use the NgModelController require: 'ngModel', // add the NgModelController as a dependency to your link function link: function($scope, $element, $attrs, ngModelCtrl) { $element.on('blur change keydown', function(evt) { $scope.$evalAsync(function($scope) { // update the $scope.password with the element's value var pwd = $scope.password = $element.val(); // resolve password strength score using zxcvbn service $scope.passwordStrength = pwd ? (pwd.length > 7 && zxcvbn.score(pwd) || 0) : null; // define the validity criterion for okPassword constraint ngModelCtrl.$setValidity('okPassword', $scope.passwordStrength >= 2); }); }); } }; }]);

In the preceeding code, we defined the okPassword directive with zxcvbn service as a dependency. We specified that the directive can be used either as a class or an attribute. We also specified that we need the NgModelController .

In the link function, we added an event listener on the element which is triggered on blur , change and keyup events. The event listener uses the $scope.$evalAsync() method to delay the update of the scope's properties. Also, the $setValidity() method of the NgModelController was used to define the validity criterion for the okPassword validation constraint.

Finally, we go ahead to add the ok-password attribute or class to our password element to ensure that the validation constraint defined in our directive is applied.

<input type="password" class="form-control ok-password" ng-class="(joinTeamForm.password.$dirty && joinTeamForm.password.$invalid) ? 'error' : ''" id="password" name="password" placeholder="Enter Password" ng-required="true" ng-model="password">

Now we can get visual feedback for our password strength as we type. See the following screenshot:


Password Strength Meter in AngularJS 1.x
Conclusion

In this tutorial, we have been able to implement a password strength meter based on the zxcvbn Javascript library in our AngularJS application. For a detailed usage guide and documentation of the zxcvbn library, see the zxcvbn repository on Github. For a complete code sample of this tutorial, checkout the password-strength-demo repository on Github. You can also get a live demo of this tutorial on jsFiddle .

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

主题: AngularJSCSSHTMLGitBootstrapJavaHTML5UATwitter
分页:12
转载请注明
本文标题:Password Strength Meter in AngularJS 1.x
本站链接:http://www.codesec.net/view/522819.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(65)