¡Hola, desbordamiento de pila!
Esta es la primera vez que publico en el sitio, así que tenga paciencia conmigo y con mi pregunta. Mi clase tenía la tarea de crear individualmente un generador de contraseñas usando JavaScript. Afortunadamente, había logrado que la mayor parte de la aplicación funcionara correctamente, pero me he quedado atascado en un problema.
Ejemplo: el usuario elige tener 8 caracteres en su contraseña y elige incluir caracteres especiales, en minúsculas y en mayúsculas. Cuando se genera la contraseña, a veces no incluirá todas las selecciones de caracteres. (A veces generará una contraseña con caracteres especiales y en mayúsculas, pero sin un solo carácter en minúsculas).
He terminado con esta tarea por un minuto, pero mi objetivo es entender qué puedo hacer para solucionar este problema y completar esta aplicación de todos modos. Estaba pensando en eliminar potencialmente el objeto passwordOptions y convertir cada opción en una matriz propia, ¿cuáles son sus pensamientos?
¡Muchas gracias por cualquier sugerencia! :D
// passwordOptions contains all necessary string data needed to generate the password const passwordOptions = { num: "1234567890", specialChar: "!@#$%&'()*+,^-./:;<=>?[]_`{~}|", lowerCase: "abcdefghijklmnopqrstuvwxyz", upperCase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }; document.getElementById('generate').addEventListener('click', function() { alert(generatePassword()); }); // Executes when button is clicked let generatePassword = function() { // initial state for password information let passInfo = ""; // ask user for the length of their password let characterAmount = window.prompt("Enter the amount of characters you want for your password. NOTE: Must be between 8-128 characters"); // If the character length doesn't match requirements, alert the user if (characterAmount >= 8 && characterAmount < 129) { // ask if user wants to include integers let getInteger = window.confirm("Would you like to include NUMBERS?"); // if user wants to include numbers if (getInteger) { // add numerical characters to password data passInfo = passInfo + passwordOptions.num; }; // ask if user wants to include special characters let getSpecialCharacters = window.confirm("Would you like to include SPECIAL characters?"); // if user wants to include special characters if (getSpecialCharacters) { // add special characters to password data passInfo = passInfo + passwordOptions.specialChar; }; // ask if user wants to include lowercase characters let getLowerCase = window.confirm("Would you like to include LOWERCASE characters?"); // if user wants to include lowercase characters if (getLowerCase) { // add lowercase characters to password data passInfo = passInfo + passwordOptions.lowerCase; }; // ask if user wants to include uppercase characters let getUpperCase = window.confirm("Would you like to include UPPERCASE characters?"); // if user wants to include uppercase characters if (getUpperCase) { // add uppercase characters to password data passInfo = passInfo + passwordOptions.upperCase; }; // ensure user chooses at least one option if (getInteger !=true && getSpecialCharacters !=true && getLowerCase !=true && getUpperCase !=true) { // notify user needs to select at least one option window.alert("You need to select at least one option, please try again!"); // return user back to their questions return generatePassword(); }; // randomPassword is an empty string that the for loop will pass information in let randomPassword = ""; // for loop grabs characterAmount to use for (let i = 0; i < characterAmount; i++) { //passInfo connects to charAt that uses both Math.floor and random to take the length of passInfo and randomize the results randomPassword += passInfo[Math.floor(Math.random() * passInfo.length)]; }; // return password results return randomPassword; } // if user's response is invalid else { // alert user window.alert("You need to provide a valid length!"); // return user back to their questions /* Removed for testing purposes to break the endless loop. */ // return generatePassword(); } }; <button id="generate">Run</button>En lugar de hacerlo sobre la marcha, separe las preguntas de la función real que genera la contraseña.
Luego, simplemente cuente las opciones habilitadas y divida ese número por la longitud de la contraseña, luego esa será la cantidad de caracteres de cada conjunto que use, también puede usar ese número para repetir cada conjunto para promediar el total de caracteres necesarios para la contraseña
generatePassword(32, { numbers: true, special: true, lowerCase: true, upperCase: true }) aDq.6@9l%Hx=OgS'(3WZNI?372siy12$
function generatePassword(len, options) { const chars = { num: "1234567890", specialChar: "!@#$%&'()*+,^-./:;<=>?[]_`{~}|", lowerCase: "abcdefghijklmnopqrstuvwxyz", upperCase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", custom: options.custom || undefined }; const shuffleStr = str => str.split('').sort(() => 0.5 - Math.random()).join('') const factor = Math.ceil(len / Object.values(options).reduce((a, b) => b ? a + 1 : a, 0)) let str = '' if (options.numbers) str += shuffleStr(chars.num.repeat(factor)).substr(0, factor) if (options.special) str += shuffleStr(chars.specialChar.repeat(factor)).substr(0, factor) if (options.lowerCase) str += shuffleStr(chars.lowerCase.repeat(factor)).substr(0, factor) if (options.upperCase) str += shuffleStr(chars.upperCase.repeat(factor)).substr(0, factor) if (options.custom) str += shuffleStr(chars.custom.repeat(factor)).substr(0, factor) return shuffleStr(str).substr(0, len) } console.log(generatePassword(32, { numbers: true, special: true, lowerCase: true, upperCase: true })) console.log(generatePassword(32, { numbers: true, special: false, lowerCase: false, upperCase: false })) console.log(generatePassword(32, { numbers: false, special: true, lowerCase: false, upperCase: false })) console.log(generatePassword(32, { numbers: false, special: false, lowerCase: true, upperCase: false })) console.log(generatePassword(32, { numbers: false, special: false, lowerCase: false, upperCase: true })) console.log(generatePassword(32, { custom: 'abc1' }))