«
»
JavaScriptjQueryWEB

Как построить счетчик пароля в React

Как построить счетчик пароля в React

Введение

Введение
Пароли обычно используются для аутентификации пользователей в большинстве веб-приложений. Из-за этого важно, чтобы пароли сохранялись безопасным способом. На протяжении многих лет такие методы, как одностороннее хеширование паролей , использовались для сокрытия реального представления паролей, хранящихся в базе данных.

Хотя хеширование паролей является отличным шагом к обеспечению безопасности паролей, пользователь по-прежнему представляет собой серьезную проблему для безопасности паролей: пользователь, использующий в качестве пароля общее слово, делает попытки хэширования бесплодными, поскольку атака методом перебора может быстро взломать такие пароли. 

Чтобы решить эту проблему, многие веб-приложения сегодня настаивают на том, чтобы у пользователей были надежные пароли, либо путем обеспечения минимальной длины пароля, либо некоторой комбинации буквенно-цифровых символов и символов в пароле. Для измерения надежности пароля Dropbox разработал алгоритм реалистичной оценки надежности пароля, основанный на взломщиках паролей. Этот алгоритм упакован в библиотеку JavaScript с именем zxcvbn. Кроме того, пакет содержит словарь часто используемых английских слов, имен и паролей.

В этом руководстве мы создадим форму с полями для полного имени, адреса электронной почты и пароля с использованием инфраструктуры React JavaScript. Мы выполним некоторую облегченную проверку формы, а также будем использовать zxcvbnбиблиотеку для оценки надежности пароля в форме, обеспечивая при этом визуальную обратную связь.

Посмотрите демоверсию CodeSandbox о том, что вы создадите к концу этого урока.

Предпосылки

Предпосылки
Прежде чем начать, убедитесь, что в вашей системе установлена последняя версия Node .

Чтобы следовать этому уроку, вам понадобится следующее:

  • На вашем компьютере установлена последняя версия Node . Для получения дополнительной информации о том, как установить это, выберите свой дистрибутив из коллекции Как установить Node.js.
  • yarnУстанавливается для запуска всех ваших сценариев NPM и установки зависимостей для проекта. Вы можете следовать этому руководству по установке пряжи для установки yarnв вашей системе.

Шаг 1 – Настройка приложения

Шаг 1 – Настройка приложения
В этом руководстве будет использован create-react-appпакет для создания нового приложения React. Запустите следующую команду для установки create-react-appв вашей системе, если вы еще не установили ее:

npm install -g create-react-app

После завершения установки запустите новое приложение React с помощью следующей команды:

create-react-app react-password-strength

Эта команда называет это имя react-password-strength, но вы можете назвать его как угодно.

Примечание. Если вы используете npmверсию 5.2 или выше, она поставляется с дополнительным npxдвоичным файлом. Используя npxбинарный файл, вам не нужно устанавливать create-react-appглобально в вашей системе. Вы можете начать новый Реагировать приложения с помощью этой команды: .npx create-react-app react-password-strength

Далее вы установите зависимости, необходимые для приложения. Выполните следующую команду, чтобы установить необходимые зависимости:

yarn add zxcvbn isemail prop-types node-sass bootstrap

Эта команда устанавливает следующие зависимости:

  • zxcvbn – вышеупомянутая библиотека для оценки надежности пароля.
  • isemail – Библиотека проверки электронной почты.
  • prop-types – Проверка во время выполнения предполагаемых типов свойств, передаваемых компонентам.
  • node-sass – Используется для компиляции файлов Sass в CSS.

Как вы могли заметить, вы установили bootstrapпакет в качестве зависимости для приложения, чтобы получить стиль по умолчанию. Чтобы включить Bootstrap в приложение, отредактируйте src/index.jsфайл и добавьте следующую строку перед каждым другим importоператором:

SRC / index.js

import 'bootstrap/dist/css/bootstrap.min.css';Copy

Наконец, запустите ваше приложение:

yarn start

Приложение запущено, и разработка может начаться. Обратите внимание, что для вас была открыта вкладка браузера с функцией перезагрузки в реальном времени . Это будет синхронизироваться с изменениями в приложении по мере разработки.

На этом этапе вид вашего приложения будет выглядеть следующим образом:
Начальный вид

Шаг 2 – Сборка компонентов

Шаг 2 – Сборка компонентов
Это приложение будет использовать форму для полного имени, электронной почты и пароля. Это также выполнит некоторую легкую проверку формы на полях. На этом шаге вы создадите следующие компоненты React:

  • FormField – Обертывает поле ввода формы с его атрибутами и изменяет обработчик событий.
  • EmailField– Оборачивает письмо FormFieldи добавляет к нему логику проверки почты.
  • PasswordField– Оборачивает пароль FormFieldи добавляет к нему логику проверки пароля. Также прикрепляет измеритель прочности пароля и некоторые другие визуальные подсказки к полю.
  • JoinForm– Вымышленная форма Join Support Team, в которой находятся поля формы.

Создайте componentsкаталог внутри srcкаталога приложения для размещения всех компонентов.

FormFieldКомпонент

FormFieldКомпонент
Создайте новый файл FormField.jsв src/componentsкаталоге и добавьте в него следующий фрагмент кода:

SRC / компоненты / FormField.js

import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; class FormField extends Component { // initialize state state = { value: '', dirty: false, errors: [] } hasChanged = e => { e.preventDefault(); // destructure props - assign default dummy functions to validator and onStateChanged props const { label, required = false, validator = f => f, onStateChanged = f => f } = this.props; const value = e.target.value; const isEmpty = value.length === 0; const requiredMissing = this.state.dirty && required && isEmpty; let errors = []; if (requiredMissing) { // if required and is empty, add required error to state errors = [ ...errors, ${label} is required ]; } else if ('function' === typeof validator) { try { validator(value); } catch (e) { // if validator throws error, add validation error to state errors = [ ...errors, e.message ]; } } // update state and call the onStateChanged callback fn after the update // dirty is only changed to true and remains true on and after the first state update this.setState(({ dirty = false }) => ({ value, errors, dirty: !dirty || dirty }), () => onStateChanged(this.state)); } render() { const { value, dirty, errors } = this.state; const { type, label, fieldId, placeholder, children } = this.props; const hasErrors = errors.length > 0; const controlClass = ['form-control', dirty ? hasErrors ? 'is-invalid' : 'is-valid' : '' ].join(' ').trim(); return ( {label} {/** Render the first error if there are any errors **/} { hasErrors && { errors[0] } } {/** Render the children nodes passed to component **/} {children} ); } } FormField.propTypes = { type: PropTypes.oneOf(["text", "password"]).isRequired, label: PropTypes.string.isRequired, fieldId: PropTypes.string.isRequired, placeholder: PropTypes.string.isRequired, required: PropTypes.bool, children: PropTypes.node, validator: PropTypes.func, onStateChanged: PropTypes.func }; export default FormField;Copy

Мы делаем несколько вещей в этом компоненте. Давайте разберем это немного:

Состояние ввода : во-первых, вы инициализировали stateкомпонент поля формы для отслеживания текущего valueполя ввода, dirtyсостояния поля и любой существующей проверки errors. Поле становится грязным, как только его значение изменяется и остается грязным.

Обработка изменения ввода : Затем вы добавили hasChanged(e)обработчик событий, чтобы обновлять состояние valueдо текущего значения ввода при каждом изменении ввода. В обработчике вы также определяете dirtyсостояние поля. Вы проверяете, является ли requiredполе полем на основе реквизита, и добавляете ошибку проверки в errorsмассив состояний, если значение пустое.

Однако, если поле не является обязательным полем или является обязательным, но не пустым, вы делегируете функцию проверки, переданную в необязательном validatorобъекте prop, вызываете ее с текущим входным значением и добавляете брошенную ошибку проверки в errorsмассив состояний (если есть какая-то ошибка).

Наконец, вы обновляете состояние и передаете функцию обратного вызова для вызова после обновления. Функция обратного вызова вызывает функцию, переданную в необязательном onStateChangedобъекте prop, передавая обновленное состояние в качестве аргумента. Это станет удобным для распространения изменений состояния вне компонента.

Рендеринг и реквизит : здесь вы визуализируете поле ввода и его метку. Вы также условно отображаете первую ошибку в errorsмассиве состояний (если есть какие-либо ошибки). Обратите внимание, как вы динамически устанавливаете классы для поля ввода для отображения статуса проверки с помощью встроенных классов из Bootstrap. Вы также отображаете любые дочерние узлы, содержащиеся в компоненте.

Как видно из компонента propTypes, необходимые опоры для данного компонента type( 'text'или 'password') label, placeholderи fieldId. Остальные компоненты являются необязательными.

EmailFieldКомпонент

EmailFieldКомпонент
Создайте новый файл EmailField.jsв src/componentsкаталоге и добавьте в него следующий фрагмент кода:

SRC / компоненты / EmailField.js

import React from 'react'; import PropTypes from 'prop-types'; import { validate } from 'isemail'; import FormField from './FormField'; const EmailField = props => { // prevent passing type and validator props from this component to the rendered form field component const { type, validator, ...restProps } = props; // validateEmail function using the validate() method of the isemail package const validateEmail = value => { if (!validate(value)) throw new Error('Email is invalid'); }; // pass the validateEmail to the validator prop return }; EmailField.propTypes = { label: PropTypes.string.isRequired, fieldId: PropTypes.string.isRequired, placeholder: PropTypes.string.isRequired, required: PropTypes.bool, children: PropTypes.node, onStateChanged: PropTypes.func }; export default EmailField;Copy

В EmailFieldкомпоненте вы визуализируете FormFieldкомпонент и передаете функцию проверки электронной почты в validatorреквизит. Вы используете validate()метод isemailпакета для проверки электронной почты.

Вы можете также заметить , что все другие реквизиты , за исключением typeи validatorреквизита передаются из EmailFieldкомпонента к FormFieldкомпоненту.

PasswordFieldКомпонент

PasswordFieldКомпонент
Создайте новый файл PasswordField.jsв src/componentsкаталоге и добавьте в него следующий фрагмент кода:

SRC / компоненты / PasswordField.js

import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import zxcvbn from 'zxcvbn'; import FormField from './FormField'; class PasswordField extends Component { constructor(props) { super(props); const { minStrength = 3, thresholdLength = 7 } = props; // set default minStrength to 3 if not a number or not specified // minStrength must be a a number between 0 - 4 this.minStrength = typeof minStrength === 'number' ? Math.max( Math.min(minStrength, 4), 0 ) : 3; // set default thresholdLength to 7 if not a number or not specified // thresholdLength must be a minimum value of 7 this.thresholdLength = typeof thresholdLength === 'number' ? Math.max(thresholdLength, 7) : 7; // initialize internal component state this.state = { password: '', strength: 0 }; }; stateChanged = state => { // update the internal state using the updated state from the form field this.setState({ password: state.value, strength: zxcvbn(state.value).score }, () => this.props.onStateChanged(state)); }; validatePasswordStrong = value => { // ensure password is long enough if (value.length <= this.thresholdLength) throw new Error("Password is short"); // ensure password is strong enough using the zxcvbn library if (zxcvbn(value).score < this.minStrength) throw new Error("Password is weak"); }; render() { const { type, validator, onStateChanged, children, ...restProps } = this.props; const { password, strength } = this.state; const passwordLength = password.length; const passwordStrong = strength >= this.minStrength; const passwordLong = passwordLength > this.thresholdLength; // dynamically set the password length counter class const counterClass = ['badge badge-pill', passwordLong ? passwordStrong ? 'badge-success' : 'badge-warning' : 'badge-danger'].join(' ').trim(); // password strength meter is only visible when password is not empty const strengthClass = ['strength-meter mt-2', passwordLength > 0 ? 'visible' : 'invisible'].join(' ').trim(); return ( {/** Pass the validation and stateChanged functions as props to the form field **/} To conform with our Strong Password policy, you are required to use a sufficiently strong password. Password must be more than 7 characters. {children} {/** Render the password strength meter **/} {/** Render the password length counter indicator **/} { passwordLength ? passwordLong ? ${this.thresholdLength}+ : passwordLength : '' } ); } } PasswordField.propTypes = { label: PropTypes.string.isRequired, fieldId: PropTypes.string.isRequired, placeholder: PropTypes.string.isRequired, required: PropTypes.bool, children: PropTypes.node, onStateChanged: PropTypes.func, minStrength: PropTypes.number, thresholdLength: PropTypes.number }; export default PasswordField;Copy

Этот компонент использует zxcvbnпакет оценки надежности пароля JavaScript. Пакет экспортирует zxcvbn()функцию, которая принимает строку пароля в качестве первого аргумента и возвращает объект с несколькими свойствами для оценки надежности пароля. В этом уроке мы будем интересоваться только свойством Score, которое является целым числом от 04, которое может быть полезно для реализации индикатора визуальной силы.

Вот разбивка того, что происходит в PasswordFieldкомпоненте:

Инициализация : в constructor(), вы создали два свойства экземпляра, thresholdLangthи minStrengthиз их соответствующих свойств передаются компоненту. thresholdLengthМинимальная длина пароля , прежде чем его можно считать достаточно долго. По умолчанию он 7не может быть ниже. Это minStrengthминимальная zxcvbnоценка, прежде чем пароль будет считаться достаточно надежным. Его значение варьируется от 0-4. По умолчанию, 3если не указано.

Вы также инициализировали внутреннее состояние поля пароля, чтобы сохранить текущий passwordи пароль strength.

Обработка изменений пароля : вы определили функцию проверки пароля, которая будет передана в validatorопору базового FormFieldкомпонента. Функция гарантирует, что длина пароля больше, чем, thresholdLengthа также имеет минимальную zxcvbn()оценку из указанных minStrength.

Вы также определили stateChanged()функцию, которая будет передана в onStateChangedопору FormFieldкомпонента. Эта функция извлекает обновленное состояние FormFieldкомпонента и использует его для вычисления и обновления нового внутреннего состояния PasswordFieldкомпонента.

Функция обратного вызова будет вызываться после обновления внутреннего состояния. Функция обратного вызова вызывает функцию, переданную в необязательной onStateChangedпропе PasswordFieldкомпонента, передавая обновленное FormFieldсостояние в качестве аргумента.

Рендеринг и реквизиты : здесь вы визуализировали базовый FormFieldкомпонент вместе с некоторыми элементами для подсказки ввода , индикатора надежности пароля и счетчика длины пароля .

Измеритель надежности пароля отображает strengthтекущее значение в passwordзависимости от состояния и настроен на динамическое invisibleизменение длины пароля 0. Метр покажет разные цвета для разных уровней прочности.

Счетчик длины пароля указывает, когда пароль достаточно длинный. Он показывает длину пароля, если пароль не длиннее, чем в thresholdLengthпротивном случае, он показывает thresholdLengthпосле plus(+).

PasswordFieldКомпонент принимает два дополнительных необязательных полей, minStrengthи thresholdLength, как это определено в Компонента propTypes.

JoinFormКомпонент

JoinFormКомпонент
Создайте новый файл JoinForm.jsв src/componentsкаталоге и добавьте в него следующий фрагмент кода:

SRC / компоненты / JoinForm.js

import React, { Component } from 'react'; import FormField from './FormField'; import EmailField from './EmailField'; import PasswordField from './PasswordField'; class JoinForm extends Component { // initialize state to hold validity of form fields state = { fullname: false, email: false, password: false } // higher-order function that returns a state change watch function // sets the corresponding state property to true if the form field has no errors fieldStateChanged = field => state => this.setState({ [field]: state.errors.length === 0 }); // state change watch functions for each field emailChanged = this.fieldStateChanged('email'); fullnameChanged = this.fieldStateChanged('fullname'); passwordChanged = this.fieldStateChanged('password'); render() { const { fullname, email, password } = this.state; const formValidated = fullname && email && password; // validation function for the fullname // ensures that fullname contains at least two names separated with a space const validateFullname = value => { const regex = /^[a-z]{2,}(\s[a-z]{2,})+$/i; if (!regex.test(value)) throw new Error('Fullname is invalid'); }; return ( Support Team {/** Show the form button only if all fields are valid **/} { formValidated && Join } {/** Render the fullname form field passing the name validation fn **/} {/** Render the email field component **/} {/** Render the password field component using thresholdLength of 7 and minStrength of 3 **/} ); } } export default JoinForm;Copy

JoinFormКомпонент упаковывает компоненты полой формы , которые составляют нашу форму. Мы инициализируемся состояние держать справедливость три полех формы: fullname, emailи password. Они все falseили invalidизначально.

Мы также определили функции отслеживания изменений состояния для каждого поля, чтобы соответствующим образом обновить состояние формы. Функция наблюдения проверяет, нет ли errorsв поле значений, и обновляет внутреннее состояние формы для этого поля true, или valid. Эти функции наблюдения затем назначаются для onStateChangedкаждого компонента поля формы для отслеживания изменений состояния.

Наконец, форма представляется. Обратите внимание, что вы добавили функцию проверки в fullnameполе, чтобы обеспечить предоставление как минимум двух имен, разделенных пробелом и содержащих только буквы алфавита.

AppКомпонент

AppКомпонент
До этого момента браузер по-прежнему отображал шаблонное приложение React. Теперь вы измените App.jsфайл в srcкаталоге для отображения JoinFormвнутри AppComponent.

App.jsФайл будет выглядеть следующий фрагмент:

SRC / App.js

import React from 'react'; import JoinForm from './components/JoinForm'; import './App.css'; function App() { return ( ); } export default App;Copy

Шаг 3 – Стилизация с помощью Sass

Шаг 3 – Стилизация с помощью Sass
Вы находитесь в одном шаге от окончательного вида вашего приложения. На данный момент все может показаться немного неуместным. На этом шаге вы определите некоторые правила стиля для стилизации формы.

Чтобы воспользоваться преимуществами мощных переменных Sass, вложенности и циклов, мы предварительно установили зависимость node-sass. Вы используете Sass для создания CSS-файла, который могут понять браузеры.

Есть две вещи, которые вам нужно изменить, чтобы использовать Sass в вашем приложении после установки зависимости:

  • Переименуйте файл src/App.cssв src/App.scss.
  • Отредактируйте строку импорта так, src/App.jsчтобы она ссылалась на переименованный файл.

После переименования src/App.cssфайла обновите src/App.jsфайл до следующего:

SRC / App.js

import './App.scss';Copy

Сохраните и закройте файл.

Затем замените существующее содержимое App.scssфайла следующим кодом для форматирования приложения:

SRC / App.scss

/** Declare some variables **/ $primary: #007bff; // Password strength meter color for the different levels $strength-colors: (darkred, orangered, orange, yellowgreen, green); // Gap width between strength meter bars $strength-gap: 6px; body { font-size: 62.5%; } .main-container { width: 400px; top: 0; bottom: 0; left: 0; right: 0; } .form-container { bottom: 100px; } legend.form-label { font-size: 1.5rem; color: desaturate(darken($primary, 10%), 60%); } .control-label { font-size: 0.8rem; font-weight: bold; color: desaturate(darken($primary, 10%), 80%); } .form-control { font-size: 1rem; } .form-hint { font-size: 0.6rem; line-height: 1.4; margin: -5px auto 5px; color: #999; &.error { color: #C00; font-size: 0.8rem; } } button.btn { letter-spacing: 1px; font-size: 0.8rem; font-weight: 600; } .password-count { bottom: 16px; right: 10px; font-size: 1rem; } .strength-meter { position: relative; height: 3px; background: #DDD; margin: 7px 0; border-radius: 2px; // Dynamically create the gap effect &:before, &:after { content: ''; height: inherit; background: transparent; display: block; border-color: #FFF; border-style: solid; border-width: 0 $strength-gap 0; position: absolute; width: calc(20% + #{$strength-gap}); z-index: 10; } // Dynamically create the gap effect &:before { left: calc(20% - #{($strength-gap / 2)}); } // Dynamically create the gap effect &:after { right: calc(20% - #{($strength-gap / 2)}); } } .strength-meter-fill { background: transparent; height: inherit; position: absolute; width: 0; border-radius: inherit; transition: width 0.5s ease-in-out, background 0.25s; // Dynamically generate strength meter color styles @for $i from 1 through 5 { &[data-strength='#{$i - 1}'] { width: (20% * $i); background: nth($strength-colors, $i); } } }Copy

Вы успешно добавили стили, необходимые для вашего приложения. Обратите внимание на использование генерируемого контента CSS в .strength-meter:beforeи .strength-meter:afterпсевдо-элементах для добавления пробелов в измеритель силы пароля.

Вы также использовали code>@forдирективу Sass для динамической генерации цветов заливки для измерителя прочности при разных уровнях надежности пароля.

Окончательный экран приложения будет выглядеть так:
Окончательный вид
С ошибками проверки экран будет выглядеть так:
Окончательный вид с ошибками
Без каких-либо ошибок, когда все поля верны, экран будет выглядеть так:
Окончательный вид без ошибок

Вывод

Вывод
В этом руководстве вы создали измеритель надежности пароля на основе zxcvbnбиблиотеки JavaScript в приложении React. Подробное руководство по использованию и документацию zxcvbnбиблиотеки см. В zxcvbnрепозитории на GitHub. Чтобы получить полный пример кода этого руководства, ознакомьтесь с демо-версией пароля-силы-реагирования-демки на GitHub. Вы также можете получить живую демонстрацию этого урока на Code Sandbox .

Если вас интересует версия этой статьи для AngularJS, вы можете взглянуть на: Метр надежности пароля в AngularJS .

Как построить счетчик пароля в React Источник записи: https://www.digitalocean.com/community/tutorials/how-to-build-a-password-strength-meter-in-react

Источник записи: https://www.digitalocean.com

Связанные записи
LinuxWEBWordPressПанели управления

Как уменьшить нагрузку на сервер и повысить скорость WordPress с помощью Memcached | Форум Plesk

WEBWordPress

Как добавить «Режим чтения» в ваши сообщения на блоге

WEBWordPress

6 важных тенденций SEO на 2020 год и последующий период (наши мысли)

WEB

Beaker Browser - Одноранговый браузер для веб-хакеров и разработчиков.