[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:
Robert von Burg 2021-02-22 23:11:15 +01:00
parent daad639f9c
commit 64596cdfb5
16 changed files with 403 additions and 74 deletions

View File

@ -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");

View File

@ -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));
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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>

View File

@ -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, "");

View File

@ -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;
}
}

View File

@ -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());

View File

@ -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";

View File

@ -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);

View File

@ -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=");

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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()));
}
}