I recently got rejected at a job interview for submitting this:
https://bitbucket.org/gnerr/password-validator
The interviewer asked for a password validation library that was configurable via Spring, with the following default validations:
- Must consist of a mixture of lowercase letters and numerical digits only, with at least one of each.
- Must be between 5 and 12 characters in length.
- Must not contain any sequence of characters immediately followed by the same sequence.
Unfortunately they never told me why my implementation is bad, so would someone be kind enough to tell me what I did wrong here?
Here's the main validation class for the library:
package dm.passwordvalidator;
import java.util.ArrayList;
import java.util.List;
/**
* @author dm
*
*/
public class PasswordValidator {
private List<ValidationRule> rules;
/**
* Runs all your validation rules and returns true if it's valid, false otherwise
* @param inPassword
* @return boolean true if valid, false if otherwise
*/
public boolean validate(String inPassword) {
for (ValidationRule rule : this.getRules()) {
if (!rule.validate(inPassword)) {
return false;
}
}
return true;
}
/**
* Runs all your validation rules and returns a {@link ValidationResult} with messages if
* the password was invalid
* @param inPassword
* @return {@link ValidationResult} The validation result
*/
public ValidationResult validateWithMessages(String inPassword) {
ValidationResult returnValue = new ValidationResult();
List<String> messages = new ArrayList<String>();
for (ValidationRule rule : this.getRules()) {
if (!rule.validate(inPassword)) {
messages.add(rule.getMessage());
}
}
if (messages.size() > 0) {
returnValue.setValid(false);
}
returnValue.setMessages(messages);
return returnValue;
}
public List<ValidationRule> getRules() {
return this.rules == null ? this.getDefaultRules() : this.rules;
}
public void setRules(List<ValidationRule> inRules) {
this.rules = inRules;
}
private List<ValidationRule> getDefaultRules() {
List<ValidationRule> returnValue = new ArrayList<ValidationRule>();
returnValue.add(new RegexValidationRule("(?!(.+?)\\1).*", DefaultValidatorMessages.NO_CYCLES));
returnValue.add(new RegexValidationRule("[a-z0-9]+", DefaultValidatorMessages.LOWERCASE_AND_NUMBERS));
returnValue.add(new RegexValidationRule(".*[a-z].*", DefaultValidatorMessages.LOWERCASE_AND_NUMBERS));
returnValue.add(new RegexValidationRule(".*[0-9].*", DefaultValidatorMessages.LOWERCASE_AND_NUMBERS));
returnValue.add(new RegexValidationRule(".{5,15}", DefaultValidatorMessages.FIVE_AND_TWELVE));
return returnValue;
}
}
The library is configurable as beans like this:
<bean id="lengthRule" class="dm.passwordvalidator.RegexValidationRule">
<property name="regex" value=".{5,15}"/>
<property name="message" value="Your password needs to be between 5 to 15 characters"/>
</bean>
<bean id="passwordValidator" class="dm.passwordvalidator.PasswordValidator">
<property name="rules">
<list>
<ref bean="lengthRule" />
</list>
</property>
</bean>