Reputation: 127
I have some HTML and Javascript that is asks a user to enter a password with the following rules:
This is followed by a password confirmation entry. There are div blocks below the password and password confirmation inputs that contain error messages enclosed in p tags, that are supposed to becomes visible when any of the errors occur. It doesn't seem to be working.
I am also using C# Razor code in this CSHTML file, so I'm required to use "@@" instead of @ within strings. If I'm wrong about that though, please let me know.
Password: (Must contain at least 1 lowercase alphabetical character, 1 uppercase alphabetical character, 1 special character, 1 numerica character and at least 8 characters long)
<input type="password" name="password_admin1_create" oninput="return validate_password()"><br><br>
<script>
var password = document.getElementsByName("password_admin1_create")[0];
function validatePassword(val) {
var strongRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@@#\$%\^&\*])(?=.{8,})/;
console.log(re.test(val))
return strongRegex.test(val);
}
function validate_password() {
if (validatePassword(password.value)) {
document.getElementById("password_result_invalid").style.visibility = "hidden";
document.getElementById("password_result_invalid").style.height = "0";
} else {
document.getElementById("password_result_invalid").style.visibility = "visible";
document.getElementById("password_result_invalid").style.height = "initial";
}
}
</script>
<div id="password_result_invalid" class="error_verify">
<p style="color:red">Invalid password format.</p>
</div>
<p>Please confirm the password:</p>
<input type="password" name="password_admin1_create_confirm" oninput="return validate_password_confirm()"><br><br>
<script>
var password_confirm = document.getElementsByName("password_admin1_create_confirm")[0].value;
var password = document.getElementsByName("password_admin1_create")[0].value;
function validate_password_confirm() {
if (password_confirm == password) {
document.getElementById("password_confirmation_invalid").style.visibility = "hidden";
document.getElementById("password_confirmation_invalid").style.height = "0";
} else {
document.getElementById("password_confirmation_invalid").style.visibility = "visible";
document.getElementById("password_confirmation_invalid").style.height = "initial";
}
}
</script>
<div id="password_confirmation_invalid" class="error_verify">
<p style="color:red">Passwords do not match.</p>
</div>
Upvotes: 1
Views: 8604
Reputation: 163477
The reason you keep seeing Invalid password format.
is that you first create a variable:
var password = document.getElementsByName("password_admin1_create")[0];
Then later on, you create it again, setting it directly to the value (which is empty)
var password = document.getElementsByName("password_admin1_create")[0].value;
So the variable password will always stay empty and will never pass the regex check.
Note
Also this variable password_confirm
is directly set to empty and in console.log(re.test(val))
there is no re
About the pattern
You could make some minor adjustments to your pattern:
(?=.{8,})
Asserts that what is on the right are 8+ times any char, which will also match a space.$
to assert the end of the string.For example:
^(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9])(?=[^!@#$%^&*]*[!@#$%^&*])(?=[!@#$%^&*A-Za-z0-9]{8,}$)
Your updated code might look like:
<input type="password" name="password_admin1_create" oninput="validate_password()"><br><br>
<script>
function validatePassword(password) {
return /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})/.test(password);
}
var password = document.getElementsByName("password_admin1_create")[0];
function validate_password() {
if (validatePassword(password.value)) {
document.getElementById("password_result_invalid").style.visibility = "hidden";
document.getElementById("password_result_invalid").style.height = "0";
} else {
document.getElementById("password_result_invalid").style.visibility = "visible";
document.getElementById("password_result_invalid").style.height = "initial";
}
}
</script>
<div id="password_result_invalid" class="error_verify">
<p style="color:red">Invalid password format.</p>
</div>
<p>Please confirm the password:</p>
<input type="password" name="password_admin1_create_confirm" oninput="return validate_password_confirm()"><br><br>
<script>
var password_confirm = document.getElementsByName("password_admin1_create_confirm")[0];
var password = document.getElementsByName("password_admin1_create")[0];
function validate_password_confirm() {
if (password.value === password_confirm.value) {
document.getElementById("password_confirmation_invalid").style.visibility = "hidden";
document.getElementById("password_confirmation_invalid").style.height = "0";
} else {
document.getElementById("password_confirmation_invalid").style.visibility = "visible";
document.getElementById("password_confirmation_invalid").style.height = "initial";
}
}
</script>
<div id="password_confirmation_invalid" class="error_verify">
<p style="color:red">Passwords do not match.</p>
</div>
Upvotes: 0
Reputation: 27743
My guess is that this expression might work:
^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[?!%@#$%^&*])[A-Za-z0-9?!%@#$%^&*]{8,}$
which we would add start and end anchors, and remove some of those escapings.
The expression is explained on the top right panel of regex101.com, if you wish to explore/simplify/modify it, and in this link, you can watch how it would match against some sample inputs, if you like.
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[?!%@#$%^&*])[A-Za-z0-9?!%@#$%^&*]{8,}$/gm;
const str = `Az0^AAAA
Az0^AAA
Az0^AAAAA`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
Upvotes: 0
Reputation: 1
Use pattern Regex:
"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$"
Usage:
<input type="password" name="pw" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$" title="Strong Password">
Upvotes: 0
Reputation: 5122
I made this a few weeks ago. Just posting it to see if it can help you (I know it's not the most clean one)
All requirements are shown above and are initially red.
<div class="requirements">
<ul>
<li id="length" class="red">Include at least 8 digits and three special characters</li>
<li id="uppercase" class="red">Include at least one upper case characters (A-Z)</li>
<li id="lowercase" class="red">Include at least one lower case character (a-z)</li>
<li id="numbers" class="red">Include a number (0-9)</li>
<li id="symbols" class="red">Include a symbol (!, #, $, etc.)</li>
</ul>
</div>
Add key up event handler to input fields on current page:
var inputfields = document.forms["changePasswordForm"].getElementsByTagName("input");
for (var i = 0; i < inputfields.length; i++){
inputfields[i].addEventListener('keyup', function(e){
// On every key up, check the password
var password = document.getElementById('sf_guard_user_password');
validatePassword(password.value);
})
}
Then at last my (ugly) validate password function
function validatePassword(password) {
// Minimum 8 characters
if (password.length > 7) {
document.getElementById('length').classList.remove('red');
document.getElementById('length').classList.add('green');
} else {
document.getElementById('length').classList.remove('green');
document.getElementById('length').classList.add('red');
}
// At least one uppercase
if (/[A-Z]/.test(password)) {
document.getElementById('uppercase').classList.remove('red');
document.getElementById('uppercase').classList.add('green');
} else {
document.getElementById('uppercase').classList.remove('green');
document.getElementById('uppercase').classList.add('red');
}
// At least one lowercase
if (/[a-z]/.test(password)) {
document.getElementById('lowercase').classList.remove('red');
document.getElementById('lowercase').classList.add('green');
} else {
document.getElementById('lowercase').classList.remove('green');
document.getElementById('lowercase').classList.add('red');
}
// At least one number
if (/[0-9]/.test(password)) {
document.getElementById('numbers').classList.remove('red');
document.getElementById('numbers').classList.add('green');
} else {
document.getElementById('numbers').classList.remove('green');
document.getElementById('numbers').classList.add('red');
}
// At least one symbol
if (/[$@$!%*#?&]/.test(password)) {
document.getElementById('symbols').classList.remove('red');
document.getElementById('symbols').classList.add('green');
} else {
document.getElementById('symbols').classList.remove('green');
document.getElementById('symbols').classList.add('red');
}
}
At last I'm checking on submit if all requirements are met:
document.getElementById('changePasswordForm').addEventListener('submit', function(e){
e.preventDefault();
// Once again ugly because length is fixed
if (document.getElementsByClassName('green').length > 4) {
document.getElementById('changePasswordForm').submit();
}
})
I don't know if this is going to help you. But I tried :)
Upvotes: 1
Reputation: 24
You should assign the "pattern" attribute to whatever regex expression fits your password requirements. For example:
< input type="password" id="psw" name="psw"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
title="Must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters"
required >
This link might also help: https://www.w3schools.com/howto/howto_js_password_validation.asp
Upvotes: 0