[New] Implemented PasswordStrengthHandler, Simple and Basic:
<PasswordStrengthHandler class="li.strolch.privilege.handler.BasicPasswordStrengthHandler"> <Parameters> <Parameter name="minLength" value="8"/> <Parameter name="maxLength" value="1024"/> <Parameter name="needsNumbers" value="true"/> <Parameter name="needsLowerCase" value="true"/> <Parameter name="needsUpperCase" value="true"/> <Parameter name="needsSpecialChars" value="true"/> </Parameters> </PasswordStrengthHandler>
This commit is contained in:
parent
daad639f9c
commit
64596cdfb5
|
@ -10,7 +10,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import li.strolch.privilege.base.AccessDeniedException;
|
||||
import li.strolch.privilege.base.InvalidCredentialsException;
|
||||
import li.strolch.privilege.model.UserState;
|
||||
import li.strolch.privilege.model.internal.User;
|
||||
import li.strolch.privilege.model.internal.UserHistory;
|
||||
|
@ -28,11 +27,12 @@ public abstract class BaseLdapPrivilegeHandler extends DefaultPrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||
PersistenceHandler persistenceHandler, UserChallengeHandler userChallengeHandler,
|
||||
SingleSignOnHandler ssoHandler, Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
PasswordStrengthHandler passwordStrengthHandler, PersistenceHandler persistenceHandler,
|
||||
UserChallengeHandler userChallengeHandler, SingleSignOnHandler ssoHandler,
|
||||
Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
|
||||
super.initialize(parameterMap, encryptionHandler, persistenceHandler, userChallengeHandler, ssoHandler,
|
||||
policyMap);
|
||||
super.initialize(parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
userChallengeHandler, ssoHandler, policyMap);
|
||||
|
||||
this.providerUrl = parameterMap.get("providerUrl");
|
||||
this.searchBase = parameterMap.get("searchBase");
|
||||
|
@ -42,7 +42,7 @@ public abstract class BaseLdapPrivilegeHandler extends DefaultPrivilegeHandler {
|
|||
|
||||
@Override
|
||||
protected synchronized User checkCredentialsAndUserState(String username, char[] password)
|
||||
throws InvalidCredentialsException, AccessDeniedException {
|
||||
throws AccessDeniedException {
|
||||
|
||||
// first see if this is a local user
|
||||
User internalUser = this.persistenceHandler.getUser(username);
|
||||
|
@ -148,7 +148,7 @@ public abstract class BaseLdapPrivilegeHandler extends DefaultPrivilegeHandler {
|
|||
|
||||
protected String validateLdapUsername(String username, Attributes attrs) throws NamingException {
|
||||
Attribute sAMAccountName = attrs.get("sAMAccountName");
|
||||
if (sAMAccountName == null || !username.toLowerCase().equals(sAMAccountName.get().toString().toLowerCase()))
|
||||
if (sAMAccountName == null || !username.equalsIgnoreCase(sAMAccountName.get().toString()))
|
||||
throw new AccessDeniedException(
|
||||
"Could not login with user: " + username + this.domain + " on Ldap: Wrong LDAP Data");
|
||||
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
package li.strolch.privilege.handler;
|
||||
|
||||
import static java.lang.Boolean.parseBoolean;
|
||||
import static java.lang.Integer.parseInt;
|
||||
import static li.strolch.privilege.i18n.PrivilegeMessages.getString;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class BasicPasswordStrengthHandler implements PasswordStrengthHandler {
|
||||
|
||||
protected int minLength;
|
||||
protected int maxLength;
|
||||
protected boolean needsNumbers;
|
||||
protected boolean needsLowerCase;
|
||||
protected boolean needsUpperCase;
|
||||
protected boolean needsSpecialChars;
|
||||
|
||||
@Override
|
||||
public void initialize(Map<String, String> parameterMap) {
|
||||
this.minLength = parseInt(parameterMap.getOrDefault("minLength", "8"));
|
||||
this.maxLength = parseInt(parameterMap.getOrDefault("maxLength", String.valueOf(1024)));
|
||||
this.needsNumbers = parseBoolean(parameterMap.getOrDefault("needsNumbers", "true"));
|
||||
this.needsLowerCase = parseBoolean(parameterMap.getOrDefault("needsLowerCase", "true"));
|
||||
this.needsUpperCase = parseBoolean(parameterMap.getOrDefault("needsUpperCase", "true"));
|
||||
this.needsSpecialChars = parseBoolean(parameterMap.getOrDefault("needsSpecialChars", "false"));
|
||||
|
||||
if (this.minLength < 8)
|
||||
throw new IllegalStateException("minLength can not be less than 8");
|
||||
if (this.maxLength > 1024)
|
||||
throw new IllegalStateException("maxLength can not be greater than 1024");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(Locale locale) {
|
||||
String description;
|
||||
|
||||
if (this.maxLength < 100)
|
||||
description = MessageFormat
|
||||
.format(getString(locale, "Privilege.passwordLengthBetween"), this.minLength, this.maxLength);
|
||||
else
|
||||
description = MessageFormat.format(getString(locale, "Privilege.passwordLengthAtLeast"), this.minLength);
|
||||
|
||||
if (this.needsNumbers)
|
||||
description += ", " + getString(locale, "Privilege.passwordMustContainNumbers");
|
||||
|
||||
if (this.needsLowerCase && this.needsUpperCase)
|
||||
description += ", " + getString(locale, "Privilege.passwordMustContainLowerAndUpperCase");
|
||||
else if (this.needsLowerCase)
|
||||
description += ", " + getString(locale, "Privilege.passwordMustContainLowerCase");
|
||||
else
|
||||
description += ", " + getString(locale, "Privilege.passwordMustContainUpperCase");
|
||||
|
||||
if (this.needsSpecialChars)
|
||||
description += ", " + getString(locale, "Privilege.passwordMustContainSpecialCharacters");
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateStrength(char[] password) {
|
||||
if (password.length < this.minLength || password.length > this.maxLength)
|
||||
return false;
|
||||
|
||||
boolean numbersOk = !this.needsNumbers;
|
||||
boolean lowerCaseOk = !this.needsLowerCase;
|
||||
boolean upperCaseOk = !this.needsUpperCase;
|
||||
boolean specialCharsOk = !this.needsSpecialChars;
|
||||
|
||||
for (char c : password) {
|
||||
|
||||
if (numbersOk && lowerCaseOk && upperCaseOk && specialCharsOk)
|
||||
return true;
|
||||
|
||||
if (!numbersOk && Character.isDigit(c)) {
|
||||
numbersOk = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!lowerCaseOk && Character.isLowerCase(c)) {
|
||||
lowerCaseOk = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!upperCaseOk && Character.isUpperCase(c)) {
|
||||
upperCaseOk = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!specialCharsOk && isSpecial(c))
|
||||
specialCharsOk = true;
|
||||
}
|
||||
|
||||
return numbersOk && lowerCaseOk && upperCaseOk && specialCharsOk;
|
||||
}
|
||||
|
||||
public static boolean isSpecial(char c) {
|
||||
return !(Character.isDigit(c) || Character.isLowerCase(c) || Character.isUpperCase(c));
|
||||
}
|
||||
}
|
|
@ -84,6 +84,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
*/
|
||||
protected EncryptionHandler encryptionHandler;
|
||||
|
||||
/**
|
||||
* The password strength handler is used for validating the strength of a password when being set
|
||||
*/
|
||||
protected PasswordStrengthHandler passwordStrengthHandler;
|
||||
|
||||
/**
|
||||
* The Single Sign On Handler
|
||||
*/
|
||||
|
@ -399,7 +404,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
if (password != null) {
|
||||
|
||||
// validate password meets basic requirements
|
||||
validatePassword(password);
|
||||
validatePassword(certificate.getLocale(), password);
|
||||
|
||||
// get new salt for user
|
||||
salt = this.encryptionHandler.nextSalt();
|
||||
|
@ -464,7 +469,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
if (password != null) {
|
||||
|
||||
// validate password meets basic requirements
|
||||
validatePassword(password);
|
||||
validatePassword(certificate.getLocale(), password);
|
||||
|
||||
// get new salt for user
|
||||
salt = this.encryptionHandler.nextSalt();
|
||||
|
@ -779,7 +784,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
if (password != null) {
|
||||
|
||||
// validate password meets basic requirements
|
||||
validatePassword(password);
|
||||
validatePassword(certificate.getLocale(), password);
|
||||
|
||||
// get new salt for user
|
||||
salt = this.encryptionHandler.nextSalt();
|
||||
|
@ -1484,7 +1489,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
throws InvalidCredentialsException, AccessDeniedException {
|
||||
|
||||
// and validate the password
|
||||
validatePassword(password);
|
||||
if (password == null || password.length < 3)
|
||||
throw new InvalidCredentialsException("Password is invalid!");
|
||||
|
||||
// get user object
|
||||
User user = this.persistenceHandler.getUser(username);
|
||||
|
@ -1755,21 +1761,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
return privilegeContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* This simple implementation validates that the password is not null, and that the password string is not empty
|
||||
*
|
||||
* @see li.strolch.privilege.handler.PrivilegeHandler#validatePassword(char[])
|
||||
*/
|
||||
@Override
|
||||
public void validatePassword(char[] password) throws PrivilegeException {
|
||||
|
||||
if (password == null || password.length == 0) {
|
||||
throw new PrivilegeModelException("A password may not be empty!"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (password.length < 3) {
|
||||
throw new PrivilegeModelException("The given password is shorter than 3 characters"); //$NON-NLS-1$
|
||||
}
|
||||
public void validatePassword(Locale locale, char[] password) throws PrivilegeException {
|
||||
if (!this.passwordStrengthHandler.validateStrength(password))
|
||||
throw new PrivilegeException(this.passwordStrengthHandler.getDescription(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1811,6 +1806,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
* a map containing configuration properties
|
||||
* @param encryptionHandler
|
||||
* the {@link EncryptionHandler} instance for this {@link PrivilegeHandler}
|
||||
* @param passwordStrengthHandler
|
||||
* the {@link PasswordStrengthHandler} instance for this {@link PrivilegeHandler}
|
||||
* @param persistenceHandler
|
||||
* the {@link PersistenceHandler} instance for this {@link PrivilegeHandler}
|
||||
* @param userChallengeHandler
|
||||
|
@ -1824,14 +1821,16 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
* if the this method is called multiple times or an initialization exception occurs
|
||||
*/
|
||||
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||
PersistenceHandler persistenceHandler, UserChallengeHandler userChallengeHandler,
|
||||
SingleSignOnHandler ssoHandler, Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
PasswordStrengthHandler passwordStrengthHandler, PersistenceHandler persistenceHandler,
|
||||
UserChallengeHandler userChallengeHandler, SingleSignOnHandler ssoHandler,
|
||||
Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
|
||||
if (this.initialized)
|
||||
throw new PrivilegeModelException("Already initialized!"); //$NON-NLS-1$
|
||||
|
||||
this.policyMap = policyMap;
|
||||
this.encryptionHandler = encryptionHandler;
|
||||
this.passwordStrengthHandler = passwordStrengthHandler;
|
||||
this.persistenceHandler = persistenceHandler;
|
||||
this.userChallengeHandler = userChallengeHandler;
|
||||
this.ssoHandler = ssoHandler;
|
||||
|
|
|
@ -30,11 +30,12 @@ public class JsonConfigLdapPrivilegeHandler extends BaseLdapPrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||
PersistenceHandler persistenceHandler, UserChallengeHandler userChallengeHandler,
|
||||
SingleSignOnHandler ssoHandler, Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
PasswordStrengthHandler passwordStrengthHandler, PersistenceHandler persistenceHandler,
|
||||
UserChallengeHandler userChallengeHandler, SingleSignOnHandler ssoHandler,
|
||||
Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
|
||||
super.initialize(parameterMap, encryptionHandler, persistenceHandler, userChallengeHandler, ssoHandler,
|
||||
policyMap);
|
||||
super.initialize(parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
userChallengeHandler, ssoHandler, policyMap);
|
||||
|
||||
this.realm = parameterMap.get(REALM);
|
||||
DBC.PRE.assertNotEmpty("realm must be set!", realm);
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package li.strolch.privilege.handler;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The password strength handler allows to plug-in different algorithms for validating the strength of a password
|
||||
*/
|
||||
public interface PasswordStrengthHandler {
|
||||
|
||||
/**
|
||||
* Initialize the concrete {@link PasswordStrengthHandler}. The passed parameter map contains any configuration the
|
||||
* concrete {@link PasswordStrengthHandler} might need
|
||||
*
|
||||
* @param parameterMap
|
||||
* a map containing configuration properties
|
||||
*/
|
||||
void initialize(Map<String, String> parameterMap);
|
||||
|
||||
/**
|
||||
* Returns a description what a password must contain in order to be regarded as strong for this concrete
|
||||
* implementation
|
||||
*
|
||||
* @return a description of a strong password
|
||||
* @param locale
|
||||
*/
|
||||
String getDescription(Locale locale);
|
||||
|
||||
/**
|
||||
* Performs the validation of the given password
|
||||
*
|
||||
* @param password
|
||||
* the password to validate
|
||||
*
|
||||
* @return true if the password meets the criteria for a strong password
|
||||
*/
|
||||
boolean validateStrength(char[] password);
|
||||
}
|
|
@ -775,16 +775,9 @@ public interface PrivilegeHandler {
|
|||
PrivilegeContext validate(Certificate certificate, String source) throws PrivilegeException;
|
||||
|
||||
/**
|
||||
* Validate that the given password meets certain requirements. What these requirements are is a decision made by
|
||||
* the concrete implementation
|
||||
*
|
||||
* @param password
|
||||
* the password to be validated to meet certain requirements
|
||||
*
|
||||
* @throws PrivilegeException
|
||||
* if the password does not implement the requirement of the concrete implementation
|
||||
* @see li.strolch.privilege.handler.PasswordStrengthHandler#validateStrength(char[])
|
||||
*/
|
||||
void validatePassword(char[] password) throws PrivilegeException;
|
||||
void validatePassword(Locale locale, char[] password) throws PrivilegeException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
|
|
@ -26,11 +26,12 @@ public class SimpleLdapPrivilegeHandler extends BaseLdapPrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||
PersistenceHandler persistenceHandler, UserChallengeHandler userChallengeHandler,
|
||||
SingleSignOnHandler ssoHandler, Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
PasswordStrengthHandler passwordStrengthHandler, PersistenceHandler persistenceHandler,
|
||||
UserChallengeHandler userChallengeHandler, SingleSignOnHandler ssoHandler,
|
||||
Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
|
||||
super.initialize(parameterMap, encryptionHandler, persistenceHandler, userChallengeHandler, ssoHandler,
|
||||
policyMap);
|
||||
super.initialize(parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
userChallengeHandler, ssoHandler, policyMap);
|
||||
|
||||
this.organisation = parameterMap.getOrDefault(ORGANISATION, "");
|
||||
this.location = parameterMap.getOrDefault(LOCATION, "");
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package li.strolch.privilege.handler;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class SimplePasswordStrengthHandler implements PasswordStrengthHandler {
|
||||
|
||||
@Override
|
||||
public void initialize(Map<String, String> parameterMap) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(Locale locale) {
|
||||
return "Password must be at least 3 characters long";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateStrength(char[] password) {
|
||||
return password != null && password.length >= 3;
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package li.strolch.privilege.helper;
|
||||
|
||||
import static li.strolch.utils.helper.StringHelper.isEmpty;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
|
@ -28,6 +30,8 @@ import li.strolch.privilege.policy.PrivilegePolicy;
|
|||
import li.strolch.privilege.xml.PrivilegeConfigSaxReader;
|
||||
import li.strolch.utils.helper.ClassHelper;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class implements the initializing of the {@link PrivilegeHandler} by loading an XML file containing the
|
||||
|
@ -37,6 +41,8 @@ import li.strolch.utils.helper.XmlHelper;
|
|||
*/
|
||||
public class PrivilegeInitializationHelper {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PrivilegeInitializationHelper.class);
|
||||
|
||||
/**
|
||||
* Initializes the {@link DefaultPrivilegeHandler} from the configuration file
|
||||
*
|
||||
|
@ -108,6 +114,23 @@ public class PrivilegeInitializationHelper {
|
|||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
// initialize password strength handler
|
||||
String passwordStrengthHandlerClassName = containerModel.getPasswordStrengthHandlerClassName();
|
||||
if (isEmpty(passwordStrengthHandlerClassName)) {
|
||||
logger.info("No PasswordStrengthHandler defined, using " + SimplePasswordStrengthHandler.class.getName());
|
||||
passwordStrengthHandlerClassName = SimplePasswordStrengthHandler.class.getName();
|
||||
}
|
||||
PasswordStrengthHandler passwordStrengthHandler = ClassHelper
|
||||
.instantiateClass(passwordStrengthHandlerClassName);
|
||||
parameterMap = containerModel.getPasswordStrengthHandlerParameterMap();
|
||||
try {
|
||||
passwordStrengthHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "PasswordStrengthHandler {0} could not be initialized"; //$NON-NLS-1$
|
||||
msg = MessageFormat.format(msg, passwordStrengthHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
// initialize persistence handler
|
||||
String persistenceHandlerClassName = containerModel.getPersistenceHandlerClassName();
|
||||
PersistenceHandler persistenceHandler = ClassHelper.instantiateClass(persistenceHandlerClassName);
|
||||
|
@ -164,9 +187,8 @@ public class PrivilegeInitializationHelper {
|
|||
|
||||
Map<String, Class<PrivilegePolicy>> policyMap = containerModel.getPolicies();
|
||||
try {
|
||||
privilegeHandler
|
||||
.initialize(parameterMap, encryptionHandler, persistenceHandler, challengeHandler, ssoHandler,
|
||||
policyMap);
|
||||
privilegeHandler.initialize(parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
challengeHandler, ssoHandler, policyMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "PrivilegeHandler {0} could not be initialized"; //$NON-NLS-1$
|
||||
msg = MessageFormat.format(msg, privilegeHandler.getClass().getName());
|
||||
|
|
|
@ -69,7 +69,12 @@ public class XmlConstants {
|
|||
public static final String XML_HANDLER_ENCRYPTION = "EncryptionHandler";
|
||||
|
||||
/**
|
||||
* XML_HANDLER_ENCRYPTION = "EncryptionHandler" :
|
||||
* XML_HANDLER_ENCRYPTION = "PasswordStrengthHandler" :
|
||||
*/
|
||||
public static final String XML_HANDLER_PASSWORD_STRENGTH = "PasswordStrengthHandler";
|
||||
|
||||
/**
|
||||
* XML_HANDLER_ENCRYPTION = "SsoHandler" :
|
||||
*/
|
||||
public static final String XML_HANDLER_SSO = "SsoHandler";
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package li.strolch.privilege.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
@ -29,6 +30,14 @@ public class PrivilegeMessages {
|
|||
private PrivilegeMessages() {
|
||||
}
|
||||
|
||||
public static String getString(Locale locale, String key) {
|
||||
try {
|
||||
return ResourceBundle.getBundle(BUNDLE_NAME, locale).getString(key);
|
||||
} catch (MissingResourceException e) {
|
||||
return '!' + key + '!';
|
||||
}
|
||||
}
|
||||
|
||||
public static String getString(String key) {
|
||||
try {
|
||||
return RESOURCE_BUNDLE.getString(key);
|
||||
|
|
|
@ -37,12 +37,14 @@ import li.strolch.privilege.policy.PrivilegePolicy;
|
|||
public class PrivilegeContainerModel {
|
||||
|
||||
private String encryptionHandlerClassName;
|
||||
private String passwordStrengthHandlerClassName;
|
||||
private String persistenceHandlerClassName;
|
||||
private String userChallengeHandlerClassName;
|
||||
private String ssoHandlerClassName;
|
||||
private String privilegeHandlerClassName;
|
||||
|
||||
private Map<String, String> encryptionHandlerParameterMap;
|
||||
private Map<String, String> passwordStrengthHandlerParameterMap;
|
||||
private Map<String, String> persistenceHandlerParameterMap;
|
||||
private Map<String, String> challengeHandlerParameterMap;
|
||||
private Map<String, String> ssoHandlerParameterMap;
|
||||
|
@ -50,11 +52,12 @@ public class PrivilegeContainerModel {
|
|||
|
||||
private Map<String, String> parameterMap;
|
||||
|
||||
private Map<String, Class<PrivilegePolicy>> policies;
|
||||
private final Map<String, Class<PrivilegePolicy>> policies;
|
||||
|
||||
public PrivilegeContainerModel() {
|
||||
this.policies = new HashMap<>();
|
||||
this.encryptionHandlerParameterMap = new HashMap<>();
|
||||
this.passwordStrengthHandlerParameterMap = new HashMap<>();
|
||||
this.persistenceHandlerParameterMap = new HashMap<>();
|
||||
this.challengeHandlerParameterMap = new HashMap<>();
|
||||
this.ssoHandlerParameterMap = new HashMap<>();
|
||||
|
@ -77,6 +80,22 @@ public class PrivilegeContainerModel {
|
|||
this.encryptionHandlerClassName = encryptionHandlerClassName;
|
||||
}
|
||||
|
||||
public String getPasswordStrengthHandlerClassName() {
|
||||
return this.passwordStrengthHandlerClassName;
|
||||
}
|
||||
|
||||
public void setPasswordStrengthHandlerClassName(String passwordStrengthHandlerClassName) {
|
||||
this.passwordStrengthHandlerClassName = passwordStrengthHandlerClassName;
|
||||
}
|
||||
|
||||
public Map<String, String> getPasswordStrengthHandlerParameterMap() {
|
||||
return this.passwordStrengthHandlerParameterMap;
|
||||
}
|
||||
|
||||
public void setPasswordStrengthHandlerParameterMap(Map<String, String> passwordStrengthHandlerParameterMap) {
|
||||
this.passwordStrengthHandlerParameterMap = passwordStrengthHandlerParameterMap;
|
||||
}
|
||||
|
||||
public Map<String, String> getEncryptionHandlerParameterMap() {
|
||||
return this.encryptionHandlerParameterMap;
|
||||
}
|
||||
|
@ -192,6 +211,10 @@ public class PrivilegeContainerModel {
|
|||
builder.append(this.encryptionHandlerClassName);
|
||||
builder.append(", encryptionHandlerParameterMap=");
|
||||
builder.append(this.encryptionHandlerParameterMap.size());
|
||||
builder.append(", passwordStrengthHandlerClassName=");
|
||||
builder.append(this.passwordStrengthHandlerClassName);
|
||||
builder.append(", passwordStrengthHandlerParameterMap=");
|
||||
builder.append(this.passwordStrengthHandlerParameterMap);
|
||||
builder.append(", persistenceHandlerClassName=");
|
||||
builder.append(this.persistenceHandlerClassName);
|
||||
builder.append(", persistenceHandlerParameterMap=");
|
||||
|
|
|
@ -31,9 +31,8 @@ import org.xml.sax.helpers.DefaultHandler;
|
|||
*/
|
||||
public class PrivilegeConfigSaxReader extends DefaultHandler {
|
||||
|
||||
private Deque<ElementParser> buildersStack = new ArrayDeque<>();
|
||||
|
||||
private PrivilegeContainerModel containerModel;
|
||||
private final Deque<ElementParser> buildersStack = new ArrayDeque<>();
|
||||
private final PrivilegeContainerModel containerModel;
|
||||
|
||||
public PrivilegeConfigSaxReader(PrivilegeContainerModel containerModel) {
|
||||
this.containerModel = containerModel;
|
||||
|
@ -46,12 +45,16 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
|||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
|
||||
if (qName.equals(XmlConstants.XML_CONTAINER)) {
|
||||
switch (qName) {
|
||||
case XmlConstants.XML_CONTAINER:
|
||||
this.buildersStack.push(new ContainerParser());
|
||||
} else if (qName.equals(XmlConstants.XML_PARAMETERS)) {
|
||||
break;
|
||||
case XmlConstants.XML_PARAMETERS:
|
||||
this.buildersStack.push(new ParametersParser());
|
||||
} else if (qName.equals(XmlConstants.XML_POLICIES)) {
|
||||
break;
|
||||
case XmlConstants.XML_POLICIES:
|
||||
this.buildersStack.push(new PoliciesParser());
|
||||
break;
|
||||
}
|
||||
|
||||
if (!this.buildersStack.isEmpty())
|
||||
|
@ -71,12 +74,12 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
|||
this.buildersStack.peek().endElement(uri, localName, qName);
|
||||
|
||||
ElementParser elementParser = null;
|
||||
if (qName.equals(XmlConstants.XML_CONTAINER)) {
|
||||
elementParser = this.buildersStack.pop();
|
||||
} else if (qName.equals(XmlConstants.XML_PARAMETERS)) {
|
||||
elementParser = this.buildersStack.pop();
|
||||
} else if (qName.equals(XmlConstants.XML_POLICIES)) {
|
||||
switch (qName) {
|
||||
case XmlConstants.XML_CONTAINER:
|
||||
case XmlConstants.XML_PARAMETERS:
|
||||
case XmlConstants.XML_POLICIES:
|
||||
elementParser = this.buildersStack.pop();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!this.buildersStack.isEmpty() && elementParser != null)
|
||||
|
@ -90,28 +93,47 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
|||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||
throws SAXException {
|
||||
if (qName.equals(XmlConstants.XML_CONTAINER)) {
|
||||
|
||||
switch (qName) {
|
||||
case XmlConstants.XML_CONTAINER:
|
||||
this.currentElement = qName;
|
||||
} else if (qName.equals(XmlConstants.XML_HANDLER_ENCRYPTION)) {
|
||||
break;
|
||||
case XmlConstants.XML_HANDLER_ENCRYPTION: {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
|
||||
getContainerModel().setEncryptionHandlerClassName(className);
|
||||
} else if (qName.equals(XmlConstants.XML_HANDLER_PERSISTENCE)) {
|
||||
break;
|
||||
}
|
||||
case XmlConstants.XML_HANDLER_PASSWORD_STRENGTH: {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
|
||||
getContainerModel().setPasswordStrengthHandlerClassName(className);
|
||||
break;
|
||||
}
|
||||
case XmlConstants.XML_HANDLER_PERSISTENCE: {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
|
||||
getContainerModel().setPersistenceHandlerClassName(className);
|
||||
} else if (qName.equals(XmlConstants.XML_HANDLER_USER_CHALLENGE)) {
|
||||
break;
|
||||
}
|
||||
case XmlConstants.XML_HANDLER_USER_CHALLENGE: {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
|
||||
getContainerModel().setUserChallengeHandlerClassName(className);
|
||||
} else if (qName.equals(XmlConstants.XML_HANDLER_SSO)) {
|
||||
break;
|
||||
}
|
||||
case XmlConstants.XML_HANDLER_SSO: {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
|
||||
getContainerModel().setSsoHandlerClassName(className);
|
||||
} else if (qName.equals(XmlConstants.XML_HANDLER_PRIVILEGE)) {
|
||||
break;
|
||||
}
|
||||
case XmlConstants.XML_HANDLER_PRIVILEGE: {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
|
||||
getContainerModel().setPrivilegeHandlerClassName(className);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,27 +144,37 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
|||
|
||||
ParametersParser parametersChild = (ParametersParser) child;
|
||||
|
||||
if (this.currentElement.equals(XmlConstants.XML_CONTAINER)) {
|
||||
switch (this.currentElement) {
|
||||
case XmlConstants.XML_CONTAINER:
|
||||
getContainerModel().setParameterMap(parametersChild.getParameterMap());
|
||||
} else if (this.currentElement.equals(XmlConstants.XML_HANDLER_ENCRYPTION)) {
|
||||
break;
|
||||
case XmlConstants.XML_HANDLER_ENCRYPTION:
|
||||
getContainerModel().setEncryptionHandlerParameterMap(parametersChild.getParameterMap());
|
||||
} else if (this.currentElement.equals(XmlConstants.XML_HANDLER_PERSISTENCE)) {
|
||||
break;
|
||||
case XmlConstants.XML_HANDLER_PASSWORD_STRENGTH:
|
||||
getContainerModel().setPasswordStrengthHandlerParameterMap(parametersChild.getParameterMap());
|
||||
break;
|
||||
case XmlConstants.XML_HANDLER_PERSISTENCE:
|
||||
getContainerModel().setPersistenceHandlerParameterMap(parametersChild.getParameterMap());
|
||||
} else if (this.currentElement.equals(XmlConstants.XML_HANDLER_USER_CHALLENGE)) {
|
||||
break;
|
||||
case XmlConstants.XML_HANDLER_USER_CHALLENGE:
|
||||
getContainerModel().setUserChallengeHandlerParameterMap(parametersChild.getParameterMap());
|
||||
} else if (this.currentElement.equals(XmlConstants.XML_HANDLER_SSO)) {
|
||||
break;
|
||||
case XmlConstants.XML_HANDLER_SSO:
|
||||
getContainerModel().setSsoHandlerParameterMap(parametersChild.getParameterMap());
|
||||
} else if (this.currentElement.equals(XmlConstants.XML_HANDLER_PRIVILEGE)) {
|
||||
break;
|
||||
case XmlConstants.XML_HANDLER_PRIVILEGE:
|
||||
getContainerModel().setPrivilegeHandlerParameterMap(parametersChild.getParameterMap());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ParametersParser extends ElementParserAdapter {
|
||||
static class ParametersParser extends ElementParserAdapter {
|
||||
|
||||
// <Parameter name="autoPersistOnPasswordChange" value="true" />
|
||||
|
||||
private Map<String, String> parameterMap = new HashMap<>();
|
||||
private final Map<String, String> parameterMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||
|
|
|
@ -15,3 +15,10 @@ Privilege.noprivilege.role=User {0} does not have the role {1}
|
|||
Privilege.noprivilege.user=User {0} does not have the privilege {1}
|
||||
Privilege.roleAccessPrivilege.unknownPrivilege=Unhandled privilege {0} for policy {1}
|
||||
Privilege.userAccessPrivilege.unknownPrivilege=Unhandled privilege {0} for policy {1}
|
||||
Privilege.passwordLengthBetween=Password must be between {0} and {1} characters long
|
||||
Privilege.passwordLengthAtLeast=Password must be at least {0} characters long
|
||||
Privilege.passwordMustContainNumbers=must contain numbers
|
||||
Privilege.passwordMustContainLowerAndUpperCase=must container lower and upper case
|
||||
Privilege.passwordMustContainLowerCase=must contain lower case
|
||||
Privilege.passwordMustContainUpperCase=must contain upper case
|
||||
Privilege.passwordMustContainSpecialCharacters=must contain special characters
|
|
@ -0,0 +1,24 @@
|
|||
Privilege.accessdenied.noprivilege=Benutzer {0} fehlt Privileg {1} benötigt von {2} mit Wert {3}
|
||||
Privilege.accessdenied.noprivilege.value=Benutzer {0} fehlt Privileg {1} mit Wert {2} benötigt von {3}
|
||||
Privilege.illegalArgument.nonstring=\ {0} has returned a non-string privilege value\!
|
||||
Privilege.illegalArgument.nonstrolchrootelement=\ {0} has returned a privilege value which is not a StrolchRootElement\!
|
||||
Privilege.illegalArgument.nonrole=\ {0} did not return a Role privilege value\!
|
||||
Privilege.illegalArgument.noncertificate=\ {0} did not return a Certificate privilege value\!
|
||||
Privilege.illegalArgument.nonuser=\ {0} did not return a User privilege value\!
|
||||
Privilege.illegalArgument.privilegeNameMismatch=The passed privilege has the name {0} but the restrictable is referencing privilege {1}
|
||||
Privilege.illegalArgument.nontuple=\ {0} did not return a Tuple privilege value\!
|
||||
Privilege.privilegeNameEmpty=The PrivilegeName for the Restrictable is null or empty: {0}
|
||||
Privilege.privilegeNull=Privilege may not be null\!
|
||||
Privilege.restrictableNull=Restrictable may not be null\!
|
||||
Privilege.noprivilege=Privileg {0} existiert nicht
|
||||
Privilege.noprivilege.role=Benutzer {0} fehlt Rolle {1}
|
||||
Privilege.noprivilege.user=Benutzer {0} fehlt Privileg {1}
|
||||
Privilege.roleAccessPrivilege.unknownPrivilege=Unbekanntes Privileg {0} für Regel {1}
|
||||
Privilege.userAccessPrivilege.unknownPrivilege=Unbekanntes Privileg {0} für Regel {1}
|
||||
Privilege.passwordLengthBetween=Passwort muss zwischen {0} und {1} Zeichen lang sein
|
||||
Privilege.passwordLengthAtLeast=Passwort muss mindesten {0} Zeichen lang sein
|
||||
Privilege.passwordMustContainNumbers=muss Zahlen beinhalten
|
||||
Privilege.passwordMustContainLowerAndUpperCase=muss grosse und kleine Buchstaben beinhalten
|
||||
Privilege.passwordMustContainLowerCase=muss kleine Buchstaben beinhalten
|
||||
Privilege.passwordMustContainUpperCase=muss grosse Buchstaben beinhalten
|
||||
Privilege.passwordMustContainSpecialCharacters=muss Spezialzeichen beinhalten
|
|
@ -0,0 +1,52 @@
|
|||
package li.strolch.privilege.test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import li.strolch.privilege.handler.BasicPasswordStrengthHandler;
|
||||
import li.strolch.privilege.handler.PasswordStrengthHandler;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BasicPasswordStrengthHandlerTest {
|
||||
|
||||
@Test
|
||||
public void testPwStrengthBasic() {
|
||||
PasswordStrengthHandler handler = new BasicPasswordStrengthHandler();
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
parameters.put("minLength", "8");
|
||||
parameters.put("maxLength", "1024");
|
||||
parameters.put("needsNumbers", "true");
|
||||
parameters.put("needsLowerCase", "true");
|
||||
parameters.put("needsUpperCase", "true");
|
||||
parameters.put("needsSpecialChars", "true");
|
||||
handler.initialize(parameters);
|
||||
|
||||
assertTrue(handler.validateStrength("Testing0!".toCharArray()));
|
||||
assertTrue(handler.validateStrength("Täëing0!".toCharArray()));
|
||||
assertTrue(handler.validateStrength("Testing0@".toCharArray()));
|
||||
assertTrue(handler.validateStrength("Testing0¼".toCharArray()));
|
||||
assertTrue(handler.validateStrength("Testing0|".toCharArray()));
|
||||
assertTrue(handler.validateStrength("+n4lJ,7&".toCharArray()));
|
||||
assertTrue(handler.validateStrength("]}`aH1&z".toCharArray()));
|
||||
assertFalse(handler.validateStrength("Tg0!".toCharArray()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPwStrengthOnlyNumbers() {
|
||||
PasswordStrengthHandler handler = new BasicPasswordStrengthHandler();
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
parameters.put("minLength", "8");
|
||||
parameters.put("maxLength", "8");
|
||||
parameters.put("needsNumbers", "true");
|
||||
parameters.put("needsLowerCase", "false");
|
||||
parameters.put("needsUpperCase", "false");
|
||||
parameters.put("needsSpecialChars", "false");
|
||||
handler.initialize(parameters);
|
||||
|
||||
assertTrue(handler.validateStrength("34534534".toCharArray()));
|
||||
assertFalse(handler.validateStrength("Testing0!".toCharArray()));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue