2

I am trying to create a program that will take input from user as a password and compare to see if the password meets the requirements. If it doesn't meet requirements, re-prompt user for password again until it meets the requirements. Here is what I have and I don't understand why it doesn't work...

import javax.swing.*;

public class Password {

public static void main(String[] args) {
    //
    String pInput = "";

    do {
        pInput = JOptionPane.showInputDialog(null, "Please enter your password.\n"
                                                    + "Your password must have 6-10 characters\n"
                                                    + "Your password must contain at least one letter and one digit");
    }
    while (authenticate(pInput) == false);

    JOptionPane.showMessageDialog(null, "Your password was successfully entered.");
}   

private static boolean authenticate(String password)
{
    // The password should be at least six characters long.
    // The password should contain at least one letter.
    // The password should have at least one digit.
     if ((password.length() > 6) &&
        (password.length() < 10) &&
        (password.matches("[a-z]")) &&
        (password.matches("[0-9]")))
         return true;
     else
         return false;
    }
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
midrigs
  • 65
  • 2
  • 9
  • 1
    I think your regular expression is off – MadProgrammer Jul 21 '14 at 04:47
  • ... I am doing what is asked of me by my teacher... I do not see the logic in that either but please don't hate, just help. – midrigs Jul 21 '14 at 04:49
  • 3
    Try something more like `^(?=.*\d)(?=.*[a-zA-Z]).{6,10}$` instead – MadProgrammer Jul 21 '14 at 04:57
  • 4
    @tripleee, legitimate real-world reason for limiting password length: to prevent people from choosing ludicrously long passwords that waste CPU time computing hashes on the server. That's a potential DoS attack. (But any length limit shorter than one full hash block is pointless.) – Wyzard Jul 21 '14 at 05:01

5 Answers5

3

If I understand your question, I would rename your authenticate() method (it's really validate()),

// validate that a password adheres to the "rules".
private static boolean validate(String password) {
  // Check for null, then a length less then 6 (and I really don't like the length()
  // > 10 check, that's a BAD requirement).
  if (password == null || password.length() < 6 || password.length() > 10) {
    return false;
  }
  boolean containsChar = false;
  boolean containsDigit = false;
  for (char c : password.toCharArray()) {
    if (Character.isLetter(c)) {
      containsChar = true;
    } else if (Character.isDigit(c)) {
      containsDigit = true;
    }
    if (containsChar && containsDigit) {
      return true;
    }
  }
  return false;
}

Personally, I would prefer to avoid a regex because they are often confusing. If it's a requirement, then the one added as a comment to the question by @MadProgrammer might be used,

private static final Pattern pattern = Pattern
    .compile("^(?=.*\\d)(?=.*[a-zA-Z]).{6,10}$"); // <-- note "\\d"

private static boolean validate(String password) {
  return pattern.matcher(password).matches();
}
Community
  • 1
  • 1
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • 1
    +1 Always nice to avoid confusing RegEx! As others have stated, it is not a good idea to limit passwords to 10 characters. Maximums may not be a bad idea, but [use something more like 72 characters](http://security.stackexchange.com/questions/17949/why-are-passwords-limited-to-16-characters). 10 characters is too easy for a brute force hack attempt, and even though it is a trivial class example, it encourages bad practices. Explain it tactfully and you will probably impress your teacher. – Rob Wise Jul 21 '14 at 05:17
  • I have updated the program with your suggestions and I have added a function that prompts the user to re-enter their password and compares the password with the password entered first. However I am unable to find why the program keeps prompting for the re-enter password stage. If you could take a look that would help a lot! – midrigs Jul 22 '14 at 15:11
  • Don't edit your question that like that! Ask a new one. I rolled back. And `if (pInput2 == pInput) {` is not how you compare Strings. That's [this question](http://stackoverflow.com/q/513832/2970947). – Elliott Frisch Jul 22 '14 at 15:12
  • @midrigs It's cool. I mean it's your question, and you can edit as much as you want before you accept an answer. But taking my answer and integrating it into your question through an edit really isn't cool (since it makes my answer [that you accepted] look wrong and really changes your question). – Elliott Frisch Jul 22 '14 at 15:33
  • No I completely understand! just some learning pains here and I am glad you corrected me so I do not do the same in the future. – midrigs Jul 22 '14 at 16:15
2

you should change :

  • password.length() >6 into password.length() >= 6

  • password.length() <10 into password.length() <=10

    because you want at least six characters long. and most ten characters long.

  • password.matches("[a-z]") into password.matches(".[a-z]+.") because .matches("[a-z]") is used for check a character not for string

this one is edited version

private static boolean authenticate(String password)
{
    // The password should be at least six characters long.
    // The password should contain at least one letter.
    // The password should have at least one digit.
     if ((password.length() >= 6) &&
        (password.length() <= 10)&&
        (password.matches(".*[a-z]+.*")) &&
        (password.matches(".*[0-9]+.*")) )
         return true;
     else
         return false;
    }
}
zelda
  • 33
  • 2
  • 9
1

Change the regex in the authentication method:

private static boolean authenticate(String password)
{
    // The password should be at least six characters long.
    // The password should contain at least one letter.
    // The password should have at least one digit.
    if ((password.length() >= 6) &&
            (password.length() <= 10) &&
            (password.matches("^(?:.*[a-z].*)(?:.*[0-9].*)$")))
        return true;
    else
        return false;
}

Using non-capturing lookahead patterns will enable the validation you want. The original version did not work because it was trying to match the password to: "[a-z]" and "[0-9]" simultaneously - a condition that will always return false!

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
0

You need to change:

  • password.length() > 6 into: password.length() >= 6
  • password.length() < 10 into: password.length() <= 10
  • (password.matches("[a-z]")) && (password.matches("[0-9]")) into: password.matches(".*[a-z]+.*") && password.matches(".*[0-9]+.*")

The first two are because you want the 6-10 range to be inclusive (so it sounds from your requirements).
The third change is because you need the regular pattern to match the entire password, not just a single character.

ethanfar
  • 3,733
  • 24
  • 43
0

I think problem is in function's if block, use following code

if ((password.length() >= 6) &&
        (password.length() <= 10) &&
        (password.matches(".*[a-z]+.*")) &&
        (password.matches(".*[0-9]+.*")))
         return true;
kamlesh
  • 154
  • 8