Password validation in Java
Buggy behavior

First you're checking the length of the passwords, and then if they are null:


if(pass1.length() &lt; 1 || pass2.length() &lt; 1 )retVal.append("Empty fields &lt;br&gt;");

if (pass1 != null &amp;&amp; pass2 != null) {



This is not going to work well: if any of the passwords were null, you would get a NullPointerException when you check length.

Also, a better way to check if a string is empty is using pass1.isEmpty().

Also, this is pointless and potentially confusing:


pass1 = pass2;



Simplify the validation logic

It would be better and more efficient to create private final Pattern members that are compiled regular expressions, and reusable multiple times:

private final Pattern hasUppercase = Pattern.compile("[A-Z]");
private final Pattern hasLowercase = Pattern.compile("[a-z]");
private final Pattern hasNumber = Pattern.compile("\\d");
private final Pattern hasSpecialChar = Pattern.compile("[^a-zA-Z0-9 ]");


For example, this returns true if pass1 contains an uppercase character:

hasUppercase.matcher(pass1).find()


Notice the patter for hasSpecialChar: match non-alphabetic, non-digit, non-space.

Suggested implementation

Based on the above tips, you can simplify your implementation like this:

private final Pattern hasUppercase = Pattern.compile("[A-Z]");
private final Pattern hasLowercase = Pattern.compile("[a-z]");
private final Pattern hasNumber = Pattern.compile("\\d");
private final Pattern hasSpecialChar = Pattern.compile("[^a-zA-Z0-9 ]");

public String validateNewPass(String pass1, String pass2) {
    if (pass1 == null || pass2 == null) {
        logger.info("Passwords = null");
        return "One or both passwords are null";
    }

    StringBuilder retVal = new StringBuilder();

    if (pass1.isEmpty() || pass2.isEmpty()) {
        retVal.append("Empty fields &lt;br&gt;");
    }

    if (pass1.equals(pass2)) {
        logger.info(pass1 + " = " + pass2);

        if (pass1.length() &lt; 11) {
            logger.info(pass1 + " is length &lt; 11");
            retVal.append("Password is too short. Needs to have 11 characters &lt;br&gt;");
        }

        if (!hasUppercase.matcher(pass1).find()) {
            logger.info(pass1 + " &lt;-- needs uppercase");
            retVal.append("Password needs an upper case &lt;br&gt;");
        }

        if (!hasLowercase.matcher(pass1).find()) {
            logger.info(pass1 + " &lt;-- needs lowercase");
            retVal.append("Password needs a lowercase &lt;br&gt;");
        }

        if (!hasNumber.matcher(pass1).find()) {
            logger.info(pass1 + "&lt;-- needs a number");
            retVal.append("Password needs a number &lt;br&gt;");
        }

        if (!hasSpecialChar.matcher(pass1).find()) {
            logger.info(pass1 + "&lt;-- needs a specail character");
            retVal.append("Password needs a special character i.e. !,@,#, etc.  &lt;br&gt;");
        }
    } else {
        logger.info(pass1 + " != " + pass2);
        retVal.append("Passwords don't match&lt;br&gt;");
    }
    if (retVal.length() == 0) {
        logger.info("Password validates");
        retVal.append("Success");
    }

    return retVal.toString();
}


Support for unicode

If you want to allow unicode characters in the password, define the patterns using the special java character classes, as documented in the javadoc:

private final Pattern hasUppercase = Pattern.compile("\\p{javaUpperCase}");
private final Pattern hasLowercase = Pattern.compile("\\p{javaLowerCase}");
private final Pattern hasNumber = Pattern.compile("\\p{javaDigit}");
private final Pattern hasSpecialChar = Pattern.compile("[^\\p{javaLetterOrDigit} ]");