use of org.openmrs.api.WeakPasswordException in project openmrs-core by openmrs.
the class OpenmrsUtil method validatePassword.
/**
* Utility to check the validity of a password for a certain {@link User}. Passwords must be
* non-null. Their required strength is configured via global properties:
* <table summary="Configuration props">
* <tr>
* <th>Description</th>
* <th>Property</th>
* <th>Default Value</th>
* </tr>
* <tr>
* <th>Require that it not match the {@link User}'s username or system id
* <th>{@link OpenmrsConstants#GP_PASSWORD_CANNOT_MATCH_USERNAME_OR_SYSTEMID}</th>
* <th>true</th>
* </tr>
* <tr>
* <th>Require a minimum length
* <th>{@link OpenmrsConstants#GP_PASSWORD_MINIMUM_LENGTH}</th>
* <th>8</th>
* </tr>
* <tr>
* <th>Require both an upper and lower case character
* <th>{@link OpenmrsConstants#GP_PASSWORD_REQUIRES_UPPER_AND_LOWER_CASE}</th>
* <th>true</th>
* </tr>
* <tr>
* <th>Require at least one numeric character
* <th>{@link OpenmrsConstants#GP_PASSWORD_REQUIRES_DIGIT}</th>
* <th>true</th>
* </tr>
* <tr>
* <th>Require at least one non-numeric character
* <th>{@link OpenmrsConstants#GP_PASSWORD_REQUIRES_NON_DIGIT}</th>
* <th>true</th>
* </tr>
* <tr>
* <th>Require a match on the specified regular expression
* <th>{@link OpenmrsConstants#GP_PASSWORD_CUSTOM_REGEX}</th>
* <th>null</th>
* </tr>
* </table>
*
* @param username user name of the user with password to validated
* @param password string that will be validated
* @param systemId system id of the user with password to be validated
* @throws PasswordException
* @since 1.5
* @should fail with short password by default
* @should fail with short password if not allowed
* @should pass with short password if allowed
* @should fail with digit only password by default
* @should fail with digit only password if not allowed
* @should pass with digit only password if allowed
* @should fail with char only password by default
* @should fail with char only password if not allowed
* @should pass with char only password if allowed
* @should fail without both upper and lower case password by default
* @should fail without both upper and lower case password if not allowed
* @should pass without both upper and lower case password if allowed
* @should fail with password equals to user name by default
* @should fail with password equals to user name if not allowed
* @should pass with password equals to user name if allowed
* @should fail with password equals to system id by default
* @should fail with password equals to system id if not allowed
* @should pass with password equals to system id if allowed
* @should fail with password not matching configured regex
* @should pass with password matching configured regex
* @should allow password to contain non alphanumeric characters
* @should allow password to contain white spaces
* @should still work without an open session
*/
public static void validatePassword(String username, String password, String systemId) throws PasswordException {
// default values for all of the global properties
String userGp = "true";
String lengthGp = "8";
String caseGp = "true";
String digitGp = "true";
String nonDigitGp = "true";
String regexGp = null;
AdministrationService svc = null;
try {
svc = Context.getAdministrationService();
} catch (APIException apiEx) {
// if a service isn't available, fail quietly and just do the
// defaults
log.debug("Unable to get global properties", apiEx);
}
if (svc != null && Context.isSessionOpen()) {
// (the session won't be open here to allow for the unit test to
// fake not having the admin service available)
userGp = svc.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_CANNOT_MATCH_USERNAME_OR_SYSTEMID, userGp);
lengthGp = svc.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_MINIMUM_LENGTH, lengthGp);
caseGp = svc.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_REQUIRES_UPPER_AND_LOWER_CASE, caseGp);
digitGp = svc.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_REQUIRES_DIGIT, digitGp);
nonDigitGp = svc.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_REQUIRES_NON_DIGIT, nonDigitGp);
regexGp = svc.getGlobalProperty(OpenmrsConstants.GP_PASSWORD_CUSTOM_REGEX, regexGp);
}
if (password == null) {
throw new WeakPasswordException();
}
if ("true".equals(userGp) && (password.equals(username) || password.equals(systemId))) {
throw new WeakPasswordException();
}
if (StringUtils.isNotEmpty(lengthGp)) {
try {
int minLength = Integer.parseInt(lengthGp);
if (password.length() < minLength) {
throw new ShortPasswordException(getMessage("error.password.length", lengthGp));
}
} catch (NumberFormatException nfe) {
log.warn("Error in global property <" + OpenmrsConstants.GP_PASSWORD_MINIMUM_LENGTH + "> must be an Integer");
}
}
if ("true".equals(caseGp) && !containsUpperAndLowerCase(password)) {
throw new InvalidCharactersPasswordException(getMessage("error.password.requireMixedCase"));
}
if ("true".equals(digitGp) && !containsDigit(password)) {
throw new InvalidCharactersPasswordException(getMessage("error.password.requireNumber"));
}
if ("true".equals(nonDigitGp) && containsOnlyDigits(password)) {
throw new InvalidCharactersPasswordException(getMessage("error.password.requireLetter"));
}
if (StringUtils.isNotEmpty(regexGp)) {
try {
Pattern pattern = Pattern.compile(regexGp);
Matcher matcher = pattern.matcher(password);
if (!matcher.matches()) {
throw new InvalidCharactersPasswordException(getMessage("error.password.different"));
}
} catch (PatternSyntaxException pse) {
log.warn("Invalid regex of " + regexGp + " defined in global property <" + OpenmrsConstants.GP_PASSWORD_CUSTOM_REGEX + ">.");
}
}
}
Aggregations