1

Given a password, I am trying to validate if it passes all validation rules such as

  1. Be at least 6 characters long
  2. Contain at least one letter (a-z or A-Z)
  3. Contain at least one number (0-9)
  4. Contain at least one special character (@, ,ドル %, etc)

So I am creating a common validation class which can be used for in any of my applications. Below are the following scenarios the validation class needs to handle :

  • Passing password, confirm password as input and perform all validations.
  • Passing current password, new password, confirm password as input and perform all validations.
  • Passing username, password, confirm password as input but skip special character validation

So here is my initial idea. I created static methods for each scenario and return a Result object which will say if the validation has passed or failed. If it failed, it will contain error codes added to errors list object which the calling application will handle as needed.

/* CASE1: Passing password, confirm password as input and perform all validation */ 
public static ValidationResult validate(final String newPassword, final String newConfirmedPassword) {
 ValidationResult result = checkPassword(null, newPassword, newConfirmedPassword, false, true);
 // check for any errors in result object
 return result;
}
/* CASE 2 : Passing current password, new password, confirm password as input and perform all validation */
public static ValidationResult validate(final String oldPassword, final String newPassword, final String newConfirmedPassword) {
 ValidationResult result = checkPassword(oldPassword, newPassword, newConfirmedPassword, true, true);
 // check for any errors in result object
 return result;
}
/* CASE3: Passing username, password, confirm password as input but skip special character validation */
public static ValidationResult validate(final String userName, final String newPassword, final String newConfirmedPassword) {
 ValidationResult result = checkPassword(oldPassword, newPassword, newConfirmedPassword, true, false);
 // check for any errors in result object
 return result;
}
private static ValidationResult checkPassword(final String currentPass, final String newPass,
 final String confirmedPass, final boolean resetFlag, boolean allowSplChar) {
 ValidationResult result = new ValidationResult(true);
 if(resetFlag) {
 //check if current password app has entered is correct
 //check new password is different from current password
 }
 // check password length is between 8-14 characters 
 if (doesNotContainUpperCaseAlpha(newPass)){
 // set error code to result 
 result.getErrors().add("ERROR_NO_UPPERCASE");
 }
 if (doesNotContainLowerCaseAlpha(newPass)){
 // set error code to result 
 result.getErrors().add("ERROR_NO_LOWERCASE");
 }
 ...
 ..
 if(allowSplChar && doesNotContainSplCharacter(newPass)){
 // set error code to result 
 result.getErrors().add("ERROR_NO_SPECIAL_CHARAACTER");
 }
}

The above flow might work for the required scenarios but is there a better way this can be implemented?

Tulains Córdova
39.6k13 gold badges102 silver badges157 bronze badges
asked Aug 23, 2016 at 18:04
4
  • Possible duplicate of Style for control flow with validation checks Commented Aug 23, 2016 at 18:05
  • What do you do with username in method #3? Commented Aug 23, 2016 at 18:18
  • @TulainsCórdova check if the password and username are not same Commented Aug 23, 2016 at 18:20
  • What does resetFlag do? Commented Aug 23, 2016 at 18:49

1 Answer 1

2

Observations:

  • Method signatures are too long (5 parms!)
  • All method are statics, possible indication of a God Class
  • No flexibility considering that you want ...a common validation class which can be used for in any of my applications"
  • Validation options and user credentials are mixed (too many concerns)

My suggestion is:

  • A PasswordValidator class or interface which is responsible of validation options and performing validation
  • A credentials class or interface that holds username, new password, etc.
  • Usage: you instantiate the validator, set the validation settings (maybe a Factory method would do it for you, you can even read the validation settings from a conf file) then call validate(userCredentials);

One PNG is worth 1024 words:

enter image description here

Stubs and code:

==> PasswordValidator.java <== You might one to implement slightly different validators. If you find it too much having an interface just use the class down bellow.

public interface PasswordValidator { 
 public void setReset(boolean reset);
 public void setMinimalLength(int length);
 public void setAllowPasswordEqualsName(boolean allow);
 public void setAllowSpecialCharacters(boolean allow);
 public boolean getReset();
 public int getMinimalLength();
 public boolean getAllowPasswordEqualsName();
 public boolean getAllowSpecialCharacters(); 
 public ValidationResult validate(Credentials cred);
}

==> Credentials.java <== This one I could be a class, I used an interface to save time and space

public interface Credentials {
 public void setUserName(String userName);
 public void setOldPasssword(String oldPassword);
 public void setNewPassword(String newPassword);
 public void setConfirmedNewPassword(String confirmedNewPassword);
 public String getUserName();
 public String getOldPasssword();
 public String getNewPassword();
 public String getConfirmedNewPassword();
}

==> ValidationResult.java <== This implementation you already have

public class ValidationResult {
}

==> NicePasswordValidator.java <== A sample implementor of PasswordValidator

public class NicePasswordValidator implements PasswordValidator {
 private boolean allowSpecialCharacters;
 private boolean allowPasswordEqualsName;
 private int minimalLength;
 private boolean reset; 
 private static boolean containSpecialCharacters(String newPassword) {
 // TODO Auto-generated method stub
 return false;
 }
 private static boolean containsLowerCase(String newPassword) {
 // TODO Auto-generated method stub
 return false;
 }
 private static boolean containsUpperCase(String newPassword) {
 // TODO Auto-generated method stub
 return false;
 }
 private static boolean doesNotContainUpperCaseAlpha(String newPassword) {
 // TODO Auto-generated method stub
 return false;
 }
 @Override
 public void setReset(boolean reset) {
 this.reset=reset;
 }
 @Override
 public void setMinimalLength(int length) {
 this.minimalLength=length;
 }
 @Override
 public void setAllowPasswordEqualsName(boolean allow) {
 this.allowPasswordEqualsName=allow;
 }
 @Override
 public void setAllowSpecialCharacters(boolean allow) {
 this.allowSpecialCharacters=allow; 
 } 
 @Override
 public boolean getReset() {
 return this.reset;
 }
 @Override
 public int getMinimalLength() {
 return this.minimalLength;
 }
 @Override
 public boolean getAllowPasswordEqualsName() {
 return this.allowPasswordEqualsName;
 }
 @Override
 public boolean getAllowSpecialCharacters() {
 return this.allowSpecialCharacters;
 }
 @Override
 public ValidationResult validate(Credentials cred) {
 ValidationResult result = new ValidationResult();
 if (!this.allowPasswordEqualsName && cred.getNewPassword().endsWith(cred.getUserName())){
 // add to result
 }
 if (!cred.getNewPassword().equals(cred.getConfirmedNewPassword())){
 // add to result
 }
 if (!this.containsUpperCase(cred.getNewPassword())){
 // add to result
 }
 if (!this.containsLowerCase(cred.getNewPassword())){
 // add to result
 }
 if (!this.getAllowSpecialCharacters() && this.containSpecialCharacters(cred.getNewPassword())){
 // add to result
 }
 return result;
 }
}
answered Aug 23, 2016 at 19:32

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.