Главная->Уроки по js->Разработка плагина индикации надежности пароля
Разработка плагина индикации надежности пароля
Пароли - наиболее используемый механизм аутентификации. Даже несмотря на обилие сайтов, переходящих на многофакторную авторизацию, пароли все же сохраняют лидирующую позицию в обеспечении безопасности учетных записей. Стойкий пароль очень важен для обеспечения безопасности учетных записей, и в этой статье я покажу, как реализовать плагин, показывающий надежность пароля. И мы будем использовать библиотеку zxcvbn и jQuery для того, чтобы создать полнофункциональный плагин, который будет измерять и отображать надежность пароля. Введение Большинство пользователей далеки от технических вопросов, и их познания в области того, как работает аутентификация, весьма ограничены. И даже для технически подкованных пользователей не всегда понятно, какие пароли проще или тяжелее взломать. Например, простое увеличение длины пароля не обязательно сделает его более устойчивым ко взлому. Датчик надежности пароля измеряет его надежность. Обычно он отображает уровни вроде “очень слабый”, “слабый”, “хороший”, “надежный”, и т.д. Датчик обновляется при любом вводе символа, так что расчеты надежности должны вызываться при возникновении события onkeypress или onkeyup. При попытке пользователем создать аккаунт слабые пароли могут быть выявлены и отбракованы, что может повысить общую безопасность сайта. Вычисление надежности пароля Необходимо точно определиться с критериями надежности паролей. Многие разработчики пытаются самостоятельно задавать критерии валидации надежности пользовательских паролей. Обычно никто не принимает во внимание время, которое необходимо затратить на взлом пароля. Вместо этого большинство способов ручной валидации основываются на похожем наборе условий: количество символов использование заглавных букв, чисел и спецсимволов списки недопустимых паролей (слишком простых или наиболее часто используемых) Такие способы не дают хороших результатов надежности паролей, большинство паролей, сгенерированных по таким правилам будет крайне легко взломать. Так что нам нужна точная система, позволяющая оценить надежность пароля. zxcvbn В данном уроке мы собираемся разработать ситстему измерения надежности пароля на основе zxcvbn. Эта библиотека является довольно точным измерителем надежности паролей, и использует для проверки наборов наиболее распространенных английских слов, повторяющихся шаблонов, последовательностей, часто встречающихся английских имен для вычисления надежности. Она также позволяет добавлять слова в черный список. Результат, выдаваемый этой библиотекой намного более точен, чем самостоятельно придуманные правила. Рассмотрение математических функций, используемых в этой библиотеке для вычисления надежности пароля, выходит за рамки данной статьи. Давайте рассмотрим следующий код, который использует функцию zxcvbn. Первый аргумент функции является обязательным, в него передаем пароль, который хотим отвалидировать. В данном случае это будет слово “password”. Второй аргумент является опциональным, и может содержать массив слов, которые мы хотим добавить в черный список. Обычно мы хотим избежать случаев, когда пароль такой же, как и имя пользователя. Так мы, как минимум, занесем выбранное имя пользователя в черный список. 1 <script type="text/javascript"> 2 var blackList = ["admin"]; 3 var strength = zxcvbn("password", blackList); 4 </script> Функция zxcvbn возвращает объект со следующими свойствами: strength.entropy - измеряется в битах strength.crack_time - время, которое нужно потратить на взлом strength.crack_time_display - то же, что и предыдущее, но в человекопонятном виде (с указанием месяцев, лет, веков и т.д.) strength.score - искомая надежность пароля, которую мы и будем использовать внутри нашего датчика надежности. Данное значение лежит в диапазоне от 0 до 4, где 0 - очень слабый пароль, а 4 - надежный пароль. Неважно, насколько ваш пароль сложен - этот показатель не поднимется больше 4. strength.match_sequence - в данном свойстве описаны различные шаблоны, использованные для вычисления надежности. Это свойство является объектом-набором объектов, которые содержат шаблоны для брутфорса, словари и прочее. strength.calculation_time - время, затраченное на вычисление надежности пароля. Обычно не превышает нескольких миллисекунд Надежность пароля можно определить по большому числу параметров, но и нам не нужна излишняя сложность с его валидацией. Так что в нашем датчике мы будем использовать параметр score. При необходимости усложнить пароли можно также использовать параметры crack_time_display или crack_time в совокупности с параметром score. Делаем датчик надежности пароля Мы собираемся реализовать простой в использовании датчик надежности пароля с использованием jQuery, будем следовать стандартизованной структуре и построим его на основе шаблона плагина jQuery. Датчик можно реализовать различными путями, исходя из того, каким его хотим видеть. Некоторые плагины реализуют датчик в виде виджета, другие лишь выводят соответствующее сообщение о надежности пароля. Мы сосредоточимся на последнем виде - это дает нам больше гибкости в оформлении датчика. Вот требования к нашему датчику: нужны базовые проверки на пустой пароль и то, что значения в полях пароля и подтверждения идентичны возможно понадобятся дополнительные проверки на минимальное число символов, на допустимые символы, прочее надежность пароля выводится предопределенными уровнями, как “очень слабый”, “слабый”, “средний”, “надежный” возможность впоследствии использовать время, необходимое на взлом для улучшения надежности паролей для отдельных уровней Реализация плагина датчика надежности Сначала скачаем себе копию шаблона плагина Query с GitHub. После того, как скачаете, разместите файл в вашем проекте и переименуйте его в jquery.password.strength.js. Следующим шагом скачайте с GitHub библиотеку zxcvbn. Подключите эти файлы в вашем проекте, как это показано ниже: 01 <html> 02 <head> 03 <title>jQuery Password Strength Checker</title> 04 <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script> 05 <script type="text/javascript" src="zxcvbn.js"></script> 06 <script type="text/javascript" src="jquery.password.strength.js"></script> 07 </head> 08 <body> 09 </body> 10 </html> Откроем файл jquery.password.strength.js. Я полагаю, что вы уже знакомы с шаблоном плагина jQuery . Для начала нужно заменить имя плагина и секцию с опциями по умолчанию, как это сделано в следующем коде. Здесь мы заменили дефолтное имя плагина на PasswordStrengthManager и заменили дефолтные опции на другие опции, специфичные для плагина. У нас есть две переменные для задания значений пароля и подтверждения пароля. Также у нас есть массив для задания черного списка слов. Далее у нас есть две опции minChars и maxChars для определения своих собственных валидаторов. И, наконец, у нас есть опция advancedStrength для включения/отключения необходимого для взлома времени в расчет надежности. 1 var pluginName = "PasswordStrengthManager", 2 defaults = { 3 password: "", 4 confirm_pass : "", 5 blackList : [], 6 minChars : "", 7 maxChars : "", 8 advancedStrength : false 9 }; Далее можем перейти к конструктору, как показано в следующем коде. Здесь у нас дефолтный код из шаблона, кроме информационных настроек, которые мы использовали для хранения текста, который будет генерироваться датчиком пароля. Как только плагин будет использован на каком-либо элементе HTML, будет вызван этот метод. 1 function Plugin(element, options) { 2 this.element = element; 3 this.settings = $.extend({}, defaults, options); 4 this._defaults = defaults; 5 this._name = pluginName; 6 this.init(); 7 this.info = ""; 8 } Функция init используется для инициализации кода, специфичного для плагина, и выполняется она в начале процесса. Давайте взглянем на модифицированную функцию init. Для начала мы выполняем основные проверки - на пустое поле, на идентичность данных в обоих парольных полях. В this.settings будут содержать либо дефолтные настройки, либо настройки, переданные при инициализации плагина. Сообщения датчика хранятся в this.info. Наконец, сообщение мы запишем в элемент датчика, который передан при инициализации плагина. 1 init: function() { 2 if ("" == this.settings.password || "" == this.settings.confirm_pass) { 3 this.info = "Password fields cannot be empty"; 4 } else if (this.settings.password != this.settings.confirm_pass) { 5 this.info = "Passwords doesn't match"; 6 } 7 8 $(this.element).html(this.info); 9 }, Далее переходим в раздел валидации. Некоторые сайты внедряют дополнительные проверки, например на то, что символы пароля входят в заданный диапазон, или требуют, чтобы в паролях не содержалось определенных символов. Мы хотим реализовать два валидатора на minChars и maxChars. Давайте пропишем функции для этих проверок: 01 minChars: function() { 02 if (this.settings.password.length < this.settings.minChars) { 03 this.info = "Password should have at least " + this.settings.minChars + " characters"; 04 return false; 05 } else { 06 return true; 07 } 08 }, 09 10 maxChars: function() { 11 if (this.settings.password.length > this.settings.maxChars) { 12 this.info = "Password should have maximum of " + this.settings.maxChars + " characters"; 13 return false; 14 } else { 15 return true; 16 } 17 }, Эти функции проверяют пароль на минимальную и максимальную длину, и возвращают логическое значение. Далее нам нужен способ вызова этих функций. Для этого создадим следующую функцию под названием customValidators 01 customValidators: function() { 02 var err = 0; 03 04 if (this.settings.minChars != "") { 05 if (!this.minChars()) { 06 err++; 07 } 08 } 09 10 if (this.settings.maxChars != "") { 11 if (!this.maxChars()) { 12 err++; 13 } 14 } 15 16 return err; 17 } Здесь мы запускаем все проверки и увеличиваем значение переменной err. Как вы видите, условия if будут выполнены только в том случае, если соответствующие значения настроек не пусты. Так что если их не передать в качестве параметров при инициализации, то эти проверки не будут запущены. Наконец, вызовем эту функцию в первой строке функции init, чтобы в случае ошибки по своим проверкам мы получили сообщения об ошибке. Вычисляем надежность по zxcvbn Это заключительная часть нашего урока. В ней мы будем вычислять правдоподобную надежность пароля, используя библиотеку zxcvbn. Дополним функцию init следующим кодом: 01 init: function() { 02 var errors = this.customValidators(); 03 04 if ("" == this.settings.password || "" == this.settings.confirm_pass) { 05 this.info = "Password fields cannot be empty"; 06 } else if (this.settings.password != this.settings.confirm_pass) { 07 this.info = "Passwords doesn't match"; 08 } else if (errors == 0) { 09 var strength = zxcvbn(this.settings.password, this.settings.blackList); 10 11 switch (strength.score) { 12 case 0: 13 this.info = "Very Weak"; 14 break; 15 case 1: 16 this.info = "Very Weak"; 17 break; 18 case 2: 19 this.info = "Weak"; 20 break; 21 case 3: 22 this.info = "Medium"; 23 break; 24 case 4: 25 if (this.settings.advancedStrength) { 26 var crackTime = String(strength.crack_time_display); 27 28 if (crackTime.indexOf("years") !=-1) { 29 this.info = "Very Strong"; 30 } else if (crackTime.indexOf("centuries") !=-1) { 31 this.info = "Perfect"; 32 } 33 } else { 34 this.info = "Strong"; 35 } 36 37 break; 38 } 39 } 40 41 $(this.element).html(this.info); 42 }, Если свои проверки не обнаружат ошибки, переходим к расчету надежности пароля. Мы можем передать значение пароля и черный список заблокированных слов, заданных при инициализации плагина в функцию zxcvbn. Она выдаст результат с уже упомянутыми свойствами. Используем оператор switch для выдачи соответствующих сообщений для различных уровней надежности (от 0 до 4). Вы можете поменять значения на свои собственные уровни. Для первых четырех уровней я просто использовал соответствующие значения score. Вы также можете использовать свойство crack_time_display для разделения надежности на подуровни. В этом плагине я использовал только значение score, ограниченное значением 4. Значение crack_time_display показывает время, которое необходимо затратить на то, чтобы сломать пароль. Разобьем уровень на два подуровня, используя значение crack_time_display. Если пользователь не захочет включать расширенные настройки надежности, то будет использоваться основной уровень “Сильный”. Не стесняйтесь экспериментировать с параметрами, чтобы определить свои собственные уровни надежности. Наконец, мы модифицируем последний раздел шаблонного кода для включения возможности множественной инициализации, так как нам надо, чтобы плагин срабатывал при каждом нажатии клавиши. 1 $.fn[pluginName] = function (options) { 2 this.each(function() { 3 $.data(this, "plugin_" + pluginName, new Plugin(this, options)); 4 }); 5 return this; 6 }; Мы завершили разработку плагина. Давайте посмотрим на него в действии и проанализируем получившийся код. 01 <script type="text/javascript" > 02 $(function() { 03 $("#pass").keyup(function() { 04 initializeStrengthMeter(); 05 }); 06 07 $("#confirm_pass").keyup(function() { 08 initializeStrengthMeter(); 09 }); 10 }); 11 12 function initializeStrengthMeter() { 13 $("#pass_meter").PasswordStrengthManager({ 14 password: $("#pass").val(), 15 confirm_pass : $("#confirm_pass").val(), 16 minChars : "5", 17 maxChars : "15", 18 blackList : ["efewf"], 19 advancedStrength : true 20 }); 21 } 22 </script> Для инициализации плагина используем основную функцию initializeStrengthMeter. Эта функция будет вызвана на элементе, который будет использоваться в качестве датчика пароля. Создайте пустой div элемент, назначьте его id инициализатору плагина. Здесь перечислены все атрибуты, заданные в плагине. Вы можете добавлять или удалять их при необходимости. Наконец, необходимо вызывать эту функцию при каждом событии keyup на поле ввода пароля и подтверждения пароля. Заключение В этом уроке мы набросали простой плагин, реализующий датчик надежности пароля, в котором мы использовали библиотеку zxcvbn для получения правдоподобных данных о надежности пароля. Мы разработали плагин jQuery для обработки островных вариантов валидации паролей. Не стесняйтесь расширять данный плагин дополнительной функциональностью.