Проверка строки на длину, наличие заглавной литеры и цифры. Проверка пароля в JavaScript
Всем привет, Хочу решить задачу на Javascript без использования массива и метода find(): У пользователя запрашивается пароль, при этом длина пароля от 4-х до 30-и символов, минимум 1 прописную (большую) букву и минимум 1 цифру.
Я вижу решение данной задачи примерно так:
let pass = prompt('Введите пароль');
pass = pass.trim();
if (length.pass < 4 || length.pass > 30 || pass == pass.toLowerCase() || pass != pass.indexOf(/\d/)){
alert('Пароль не удовлетворяет условиям! Перезагрузите страницу и попробуйте ввести его еще раз.');
} else if (pass == pass.lastIndexOf(/\d/)){
alert('Пароль валидный. Добро пожаловать в аккаунт!');
} else {
alert(`Ошибка`);
}
Однако, думаю, что у меня есть ошибка в проверке наличия цифры в пароле, хотя использовала проверку и indexOf с lastIndexOf. Кто-нибудь решал аналогичную задачу?
Ответы (4 шт):
Вам придется усложнить проверку.
Вам передается строка и все цифры в строке это строки...
Придется преобразовывать каждый символ из строки и проверять значение
const pass = ['dfg', 'fhgkeydn', 'dfkjGkj8l',
'*sdkgfjkKjl8', 'jjsfljslfjsldfjlsfjlsdfjlfjsdflsdjflsdldjflsf;a',
'&slfjl9jkjJ', '12345678901234567890123445678901234567890',
'1234567890123456789O123456', '1234567890123456789@123456'];
/** @param {string} input */
function checkPass(input) {
if (input.length < 4) return false;
if (input.length > 30) return false;
let up = false;
let num = false;
const reg = /[a-zA-Zа-яА-Я]/g;
for (let i = 0; i < input.length; i++) {
/** @type {string} */
const check = input[i];
if (isNaN(parseInt(check))) { // string
if (reg.test(check)) {
if (check === check.toUpperCase()) up = true
}
} else { // число
num = true;
}
if (up && num) {
return true;
}
}
return false;
}
pass.forEach((item, index) => {
console.log(index, checkPass(item))
})
Если решение подходит, вставляем функцию в ваш код
let pass = prompt('Введите пароль');
pass = pass.trim();
if (!checkPass(pass)){
alert('Пароль не удовлетворяет условиям! Перезагрузите страницу и попробуйте ввести его еще раз.');
} else {
alert('Пароль валидный. Добро пожаловать в аккаунт!');
}
Как вариант:
function checkPasswordStrength(pwd) {
return /.{4,30}/.test(pwd) * (
+ /[a-zа-яё]/.test(pwd)
+ /[A-ZА-ЯЁ]/.test(pwd)
+ /\d/.test(pwd)
+ /[^A-Za-z0-9А-Яа-яЁё]/.test(pwd)
);
}
['change', 'keyup', 'input'].forEach(function(eventName) {
document.getElementById("pwd")
.addEventListener(eventName, function() {
document.getElementById("strength").value =
checkPasswordStrength(this.value);
});
});
<label for="pwd">Password:</label>
<p><input type="password" id="pwd" /></p>
<p><progress id="strength" value="0" max="4"></progress></p>
Такие вещи проверяются функциями валидаторами, которые будут проверять строку на соответствие нужным вам условиям.
Для каждого условия своя функция с проверкой. Эта же функция может выбросить соответствующую ошибку. Например вариант попроще:
function lengthLessThan(str, limit) {
return str.length < limit;
}
function lengthMoreThan(str, limit) {
return str.length > limit;
}
function hasCapitalLetters(str) {
return /[A-ZА-Я]/.test(str);
}
function hasDigits(str) {
return /[0-9]/.test(str);
}
function isPasswordValid(str) {
if (lengthLessThan(str, 4)) { // проверяем на длину строки
console.error('Пароль должен быть длиннее 4 символов');
return false; // если < 4 возвращаем false
}
if (lengthMoreThan(str, 30)) { // проверяем на длину строки
console.error('Пароль должен быть короче 30 символов');
return false; // если > 30 возвращаем false
}
if (!hasCapitalLetters(str)) { // проверяем строку на соответсвие с регулярным выражением, которое ищет заглавные буквы в строке
console.error('Пароль должен содержать хотя бы одну заглавную букву');
return false; // если заглавных букв нет, возвращаем false
}
if (!hasDigits(str)) { // проверяем строку на соответсвие с регулярным выражением, которое ищет цифры в строке
console.error('Пароль должен содержать хотя бы одну цифру');
return false; // если цифр нет, возвращаем false
}
return true; // если все условия соблюдены, то функция вернет true - строка str валидна
}
console.log(
isPasswordValid('absd1A'), // true
isPasswordValid('abs'), // false
isPasswordValid('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), //false
isPasswordValid('qew1'), // false
isPasswordValid('qewA'), // false
);
Такой подход хоть и понятный, но не самый лучший, т.к плохо переиспользуемый из-за захардкоженых значений в функциях. Он вполне может устроить новичка, т.к выполняет свою задачу на данный момент. Но, что если появится другая форма для ввода пароля и этот пароль должен будет соответствать уже другим требованиям? Можно конечно скопировать уже сужествующую функцию, переименовать и дополнить/изменить, но тогда получим повторение кода.
Чтобы этого избежать можно применить другой подход, где мы имеем функцию, которая будет принимать строку для валидации и массив с функциями валидаторами. Пробегая по массиву в цикле, мы можем понять на каком моменте не прошла валидация, или еcли весь цикл был пройден без ошибок, то строка будет валидной.
Реализация может быть примерно такой:
/**
* Ошибки для каждого валидатора
*/
const errors = {
minLength: (limiter) => new Error(`Пароль должен быть больше ${limiter} символов`),
maxLength: (limiter) => new Error(`Пароль должен быть меньше ${limiter} символов`),
pattern: () => new Error(`Пароль должен содержать хотя бы одну заглавную букву и одну цифру`),
};
/**
* @typedef {Object} ValidatorsResponse
*/
/**
* Объект Validators, выступающий в качестве пространства имен для функций валидаторов, так будет сразу понятно, для чего и откуда эти функции в коде
* @namespace Validators
*/
const Validators = {};
/**
* @memberof Validators
* @param {number} limit - минимально допустимое кол-во символов
* @returns {minLength~inner} - вернет функцию
*/
Validators.minLength = function(limit) {
/**
* @param {string} str
* @returns {(ValidatorsResponse | Error)}
* Проверяет длинну строки. Если длина < limit возвращает Error
*/
return function minLength(str) {
return str.length >= limit ? { [this.name]: { value: str, limit }}
: errors[this.name](limit);
}
}
/**
* @memberof Validators
* @param {number} limit - максимальное допустимое кол-во символов
* @returns {maxLength~inner} - вернет функцию
*/
Validators.maxLength = function(limit) {
/**
* @param {string} str
* @returns {(ValidatorsResponse | Error)}
* Проверяет длинну строки. Если длина > limit возвращает Error
*/
return function maxLength(str) {
return str.length <= limit ? { [this.name]: { value: str, limit }}
: errors[this.name](limit);
}
}
/**
* @memberof Validators
* @param {RegExp} regexp - регулярное выражение
* @returns {pattern~inner} - вернет функцию
*/
Validators.pattern = function(regexp) {
/**
* @param {string} str
* @returns {(ValidatorsResponse | Error)}
* Проверяет на соответствия между регулярным выражением regexp и строкой str.
*/
return function pattern(str) {
const valid = regexp.test(str); // проверяем строку с помощью регулярного выражения
return valid ? { [this.name]: { value: str }}
: errors[this.name]();
};
}
/**
* @function isPasswordValid
* @param {string} str - строка для проверки
* @params {Array} validators - массив с функциями валидаторов
* @returns {boolean} Вернет соответствующее булево значение в зависимости от валидности строки str
*/
function isPasswordValid(str, validators) {
try {
for (let validate of validators) {
const validated = validate.call(validate, str);
if (validated instanceof Error) throw validated; // если валидатор вернул ошибку, выкидываем ошибку дальше, чтобы обработать ее в блоке catch
}
return true; // если все хорошо, возвращаем true, строка прошла валидацию
} catch (err) { // обрабатываем ошибку
console.error(err.message); // выводим сообщение ошибки в консоль или в alert
return false; // возвращаем false, строка не прошла валидацию
}
};
/**
* Набор валидаторов для данного случая
*/
const validators = [
Validators.minLength(4), // length > 4
Validators.maxLength(30), // length < 30
Validators.pattern(/[A-ZА-Я]/), // есть заглавные буквы
Validators.pattern(/[0-9]/) // есть цифры
/**
* и так можно сюда сколько угодно таких функций валидаторов добавить
*/
];
console.log(
isPasswordValid('absd1A', validators), // true
isPasswordValid('abs', validators), // false
isPasswordValid('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', validators), //false
isPasswordValid('qew1', validators), // false
isPasswordValid('qewA', validators), // false
);
Добавил аннотации JSDoc и комментарии почти для каждого шага, чтобы было понятно, что и для чего.
В обоих случаях console.error можно заменить на alert - это не принципиально. И все будет работать.
Справочный материал, который может понадобится для понимания:
Можно так:
var password = document.querySelector(".password");
password.innerHTML = `
<label for="passCheckOne">введите пароль</label>
</br>
<input type="password" id="passCheckOne" minlength="8" oninput="checkPass(); passSpec()" title="">
</br>
<label for="passCheckTwo">повторите пароль</label>
</br>
<input type="password" id="passCheckTwo" minlength="4" maxlength="30" oninput="checkPass()" disabled>
</br>
</br>
<input type="submit" onsubmit="submitPass()">
`;
function passSpec() {
var passFirth = document.querySelector("#passCheckOne");
var title = document.querySelector("#passCheckOne").title;
if (!/[A-Z]/.test(passFirth.value) ||
!/[0-9]/.test(passFirth.value) ||
!/[a-z]/.test(passFirth.value) ||
passFirth.value.length < 4 ||
passFirth.value.length > 30) {
title = "пароль должен содержать минимум 4 и максимум 30 символов а также: A-Z , a-z, 0-9";
var inputDisable = document.querySelector("#passCheckTwo");
inputDisable.disabled = true;
} else {
title = "";
var inputDisable = document.querySelector("#passCheckTwo");
inputDisable.disabled = false;
}
passFirth.title = title;
}
<div class="password"></div>
<script src="main.js"></script>