[Major] Implemented soft migration to salt based privilege persistence
This commit is contained in:
parent
b07d2322ac
commit
17aeff6672
|
@ -2,6 +2,7 @@ package li.strolch.privilege.base;
|
||||||
|
|
||||||
public class PrivilegeConstants {
|
public class PrivilegeConstants {
|
||||||
|
|
||||||
|
public static final String DEFAULT_ALGORITHM_NON_SALT = "SHA-256";
|
||||||
public static final String DEFAULT_ALGORITHM = "PBKDF2WithHmacSHA512";
|
public static final String DEFAULT_ALGORITHM = "PBKDF2WithHmacSHA512";
|
||||||
public static final int DEFAULT_KEY_LENGTH = 256;
|
public static final int DEFAULT_KEY_LENGTH = 256;
|
||||||
public static final int DEFAULT_SMALL_ITERATIONS = 10000;
|
public static final int DEFAULT_SMALL_ITERATIONS = 10000;
|
||||||
|
|
|
@ -15,9 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.privilege.handler;
|
package li.strolch.privilege.handler;
|
||||||
|
|
||||||
import static li.strolch.privilege.base.PrivilegeConstants.DEFAULT_ALGORITHM;
|
import static li.strolch.privilege.base.PrivilegeConstants.*;
|
||||||
import static li.strolch.privilege.base.PrivilegeConstants.DEFAULT_ITERATIONS;
|
|
||||||
import static li.strolch.privilege.base.PrivilegeConstants.DEFAULT_KEY_LENGTH;
|
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.SecretKeyFactory;
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
@ -61,6 +59,11 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
|
||||||
*/
|
*/
|
||||||
private SecureRandom secureRandom;
|
private SecureRandom secureRandom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The non-salt algorithm for this instance
|
||||||
|
*/
|
||||||
|
private String nonSaltAlgorithm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configured algorithm for this instance
|
* The configured algorithm for this instance
|
||||||
*/
|
*/
|
||||||
|
@ -110,12 +113,30 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] hashPasswordWithoutSalt(char[] password) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
MessageDigest digest = MessageDigest.getInstance(this.nonSaltAlgorithm);
|
||||||
|
return digest.digest(new String(password).getBytes());
|
||||||
|
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new PrivilegeException(MessageFormat.format("Algorithm {0} was not found!", nonSaltAlgorithm),
|
||||||
|
e.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] hashPassword(char[] password, byte[] salt) {
|
public byte[] hashPassword(char[] password, byte[] salt) {
|
||||||
|
return hashPassword(password, salt, this.algorithm, this.iterations, this.keyLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] hashPassword(char[] password, byte[] salt, String algorithm, int iterations, int keyLength) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SecretKeyFactory skf = SecretKeyFactory.getInstance(this.algorithm);
|
SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
|
||||||
PBEKeySpec spec = new PBEKeySpec(password, salt, this.iterations, this.keyLength);
|
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, keyLength);
|
||||||
SecretKey key = skf.generateSecret(spec);
|
SecretKey key = skf.generateSecret(spec);
|
||||||
return key.getEncoded();
|
return key.getEncoded();
|
||||||
|
|
||||||
|
@ -131,11 +152,26 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
|
||||||
|
|
||||||
// get hash algorithm parameters
|
// get hash algorithm parameters
|
||||||
this.algorithm = parameterMap.getOrDefault(XmlConstants.XML_PARAM_HASH_ALGORITHM, DEFAULT_ALGORITHM);
|
this.algorithm = parameterMap.getOrDefault(XmlConstants.XML_PARAM_HASH_ALGORITHM, DEFAULT_ALGORITHM);
|
||||||
|
this.nonSaltAlgorithm = parameterMap
|
||||||
|
.getOrDefault(XmlConstants.XML_PARAM_HASH_ALGORITHM_NON_SALT, DEFAULT_ALGORITHM_NON_SALT);
|
||||||
this.iterations = Integer.parseInt(
|
this.iterations = Integer.parseInt(
|
||||||
parameterMap.getOrDefault(XmlConstants.XML_PARAM_HASH_ITERATIONS, String.valueOf(DEFAULT_ITERATIONS)));
|
parameterMap.getOrDefault(XmlConstants.XML_PARAM_HASH_ITERATIONS, String.valueOf(DEFAULT_ITERATIONS)));
|
||||||
this.keyLength = Integer.parseInt(
|
this.keyLength = Integer.parseInt(
|
||||||
parameterMap.getOrDefault(XmlConstants.XML_PARAM_HASH_KEY_LENGTH, String.valueOf(DEFAULT_KEY_LENGTH)));
|
parameterMap.getOrDefault(XmlConstants.XML_PARAM_HASH_KEY_LENGTH, String.valueOf(DEFAULT_KEY_LENGTH)));
|
||||||
|
|
||||||
|
// test non-salt hash algorithm
|
||||||
|
try {
|
||||||
|
hashPasswordWithoutSalt("test".toCharArray()); //$NON-NLS-1$
|
||||||
|
DefaultEncryptionHandler.logger.info(MessageFormat
|
||||||
|
.format("Using non-salt hashing algorithm {0}", this.nonSaltAlgorithm)); //$NON-NLS-1$
|
||||||
|
} catch (Exception e) {
|
||||||
|
String msg = "[{0}] Defined parameter {1} is invalid because of underlying exception: {2}"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat
|
||||||
|
.format(msg, EncryptionHandler.class.getName(), XmlConstants.XML_PARAM_HASH_ALGORITHM_NON_SALT,
|
||||||
|
e.getLocalizedMessage());
|
||||||
|
throw new PrivilegeException(msg, e);
|
||||||
|
}
|
||||||
|
|
||||||
// test hash algorithm
|
// test hash algorithm
|
||||||
try {
|
try {
|
||||||
hashPassword("test".toCharArray(), "test".getBytes()); //$NON-NLS-1$
|
hashPassword("test".toCharArray(), "test".getBytes()); //$NON-NLS-1$
|
||||||
|
|
|
@ -204,8 +204,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
List<RoleRep> roles = rolesStream.map(Role::asRoleRep).collect(Collectors.toList());
|
return rolesStream.map(Role::asRoleRep).collect(Collectors.toList());
|
||||||
return roles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -228,8 +227,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
List<UserRep> users = usersStream.map(User::asUserRep).collect(Collectors.toList());
|
return usersStream.map(User::asUserRep).collect(Collectors.toList());
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -241,8 +239,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
|
|
||||||
String selUserId = selectorRep.getUserId();
|
String selUserId = selectorRep.getUserId();
|
||||||
String selUsername = selectorRep.getUsername();
|
String selUsername = selectorRep.getUsername();
|
||||||
String selFirstname = selectorRep.getFirstname();
|
String selFirstName = selectorRep.getFirstname();
|
||||||
String selLastname = selectorRep.getLastname();
|
String selLastName = selectorRep.getLastname();
|
||||||
UserState selUserState = selectorRep.getUserState();
|
UserState selUserState = selectorRep.getUserState();
|
||||||
Locale selLocale = selectorRep.getLocale();
|
Locale selLocale = selectorRep.getLocale();
|
||||||
Set<String> selRoles = selectorRep.getRoles();
|
Set<String> selRoles = selectorRep.getRoles();
|
||||||
|
@ -262,60 +260,30 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
// selections
|
// selections
|
||||||
boolean userIdSelected;
|
boolean userIdSelected;
|
||||||
boolean usernameSelected;
|
boolean usernameSelected;
|
||||||
boolean firstnameSelected;
|
boolean firstNameSelected;
|
||||||
boolean lastnameSelected;
|
boolean lastNameSelected;
|
||||||
boolean userStateSelected;
|
boolean userStateSelected;
|
||||||
boolean localeSelected;
|
boolean localeSelected;
|
||||||
boolean roleSelected;
|
boolean roleSelected;
|
||||||
boolean propertySelected;
|
boolean propertySelected;
|
||||||
|
|
||||||
// userId
|
// userId
|
||||||
if (selUserId == null)
|
userIdSelected = selUserId == null || selUserId.equals(user.getUserId());
|
||||||
userIdSelected = true;
|
|
||||||
else if (selUserId.equals(user.getUserId()))
|
|
||||||
userIdSelected = true;
|
|
||||||
else
|
|
||||||
userIdSelected = false;
|
|
||||||
|
|
||||||
// username
|
// username
|
||||||
if (selUsername == null)
|
usernameSelected = selUsername == null || selUsername.equals(user.getUsername());
|
||||||
usernameSelected = true;
|
|
||||||
else if (selUsername.equals(user.getUsername()))
|
|
||||||
usernameSelected = true;
|
|
||||||
else
|
|
||||||
usernameSelected = false;
|
|
||||||
|
|
||||||
// firstname
|
// firstname
|
||||||
if (selFirstname == null)
|
firstNameSelected = selFirstName == null || selFirstName.equals(user.getFirstname());
|
||||||
firstnameSelected = true;
|
|
||||||
else if (selFirstname.equals(user.getFirstname()))
|
|
||||||
firstnameSelected = true;
|
|
||||||
else
|
|
||||||
firstnameSelected = false;
|
|
||||||
|
|
||||||
// lastname
|
// lastname
|
||||||
if (selLastname == null)
|
lastNameSelected = selLastName == null || selLastName.equals(user.getLastname());
|
||||||
lastnameSelected = true;
|
|
||||||
else if (selLastname.equals(user.getLastname()))
|
|
||||||
lastnameSelected = true;
|
|
||||||
else
|
|
||||||
lastnameSelected = false;
|
|
||||||
|
|
||||||
// user state
|
// user state
|
||||||
if (selUserState == null)
|
userStateSelected = selUserState == null || selUserState.equals(user.getUserState());
|
||||||
userStateSelected = true;
|
|
||||||
else if (selUserState.equals(user.getUserState()))
|
|
||||||
userStateSelected = true;
|
|
||||||
else
|
|
||||||
userStateSelected = false;
|
|
||||||
|
|
||||||
// locale
|
// locale
|
||||||
if (selLocale == null)
|
localeSelected = selLocale == null || selLocale.equals(user.getLocale());
|
||||||
localeSelected = true;
|
|
||||||
else if (selLocale.equals(user.getLocale()))
|
|
||||||
localeSelected = true;
|
|
||||||
else
|
|
||||||
localeSelected = false;
|
|
||||||
|
|
||||||
// roles
|
// roles
|
||||||
roleSelected = isSelectedByRole(selRoles, user.getRoles());
|
roleSelected = isSelectedByRole(selRoles, user.getRoles());
|
||||||
|
@ -324,7 +292,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
propertySelected = isSelectedByProperty(selPropertyMap, user.getProperties());
|
propertySelected = isSelectedByProperty(selPropertyMap, user.getProperties());
|
||||||
|
|
||||||
boolean selected =
|
boolean selected =
|
||||||
userIdSelected && usernameSelected && firstnameSelected && lastnameSelected && userStateSelected
|
userIdSelected && usernameSelected && firstNameSelected && lastNameSelected && userStateSelected
|
||||||
&& localeSelected && roleSelected && propertySelected;
|
&& localeSelected && roleSelected && propertySelected;
|
||||||
|
|
||||||
if (selected)
|
if (selected)
|
||||||
|
@ -378,11 +346,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
* null or empty, then true is returned, otherwise false
|
* null or empty, then true is returned, otherwise false
|
||||||
*/
|
*/
|
||||||
private boolean isSelectedByRole(Set<String> selectionRoles, Set<String> roles) {
|
private boolean isSelectedByRole(Set<String> selectionRoles, Set<String> roles) {
|
||||||
|
return selectionRoles == null || roles.containsAll(selectionRoles);
|
||||||
if (selectionRoles == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return roles.containsAll(selectionRoles);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -531,7 +495,9 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
Set<String> roles = userRep.getRoles();
|
Set<String> roles = userRep.getRoles();
|
||||||
Locale locale = userRep.getLocale();
|
Locale locale = userRep.getLocale();
|
||||||
Map<String, String> properties = userRep.getProperties();
|
Map<String, String> properties = userRep.getProperties();
|
||||||
return new User(userId, userName, passwordHash, salt, firstName, lastName, state, roles, locale, properties);
|
return new User(userId, userName, passwordHash, salt, this.encryptionHandler.getAlgorithm(),
|
||||||
|
this.encryptionHandler.getIterations(), this.encryptionHandler.getKeyLength(), firstName, lastName,
|
||||||
|
state, roles, locale, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -562,26 +528,30 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
String username = existingUser.getUsername();
|
String username = existingUser.getUsername();
|
||||||
byte[] password = existingUser.getPassword();
|
byte[] password = existingUser.getPassword();
|
||||||
byte[] salt = existingUser.getSalt();
|
byte[] salt = existingUser.getSalt();
|
||||||
String firstname = existingUser.getFirstname();
|
String firstName = existingUser.getFirstname();
|
||||||
String lastname = existingUser.getLastname();
|
String lastName = existingUser.getLastname();
|
||||||
UserState userState = existingUser.getUserState();
|
UserState userState = existingUser.getUserState();
|
||||||
Set<String> roles = existingUser.getRoles();
|
Set<String> roles = existingUser.getRoles();
|
||||||
Locale locale = existingUser.getLocale();
|
Locale locale = existingUser.getLocale();
|
||||||
Map<String, String> propertyMap = existingUser.getProperties();
|
Map<String, String> propertyMap = existingUser.getProperties();
|
||||||
|
|
||||||
|
String hashAlgorithm = existingUser.getHashAlgorithm();
|
||||||
|
int hashIterations = existingUser.getHashIterations();
|
||||||
|
int hashKeyLength = existingUser.getHashKeyLength();
|
||||||
|
|
||||||
// get updated fields
|
// get updated fields
|
||||||
if (StringHelper.isNotEmpty(userRep.getFirstname()))
|
if (StringHelper.isNotEmpty(userRep.getFirstname()))
|
||||||
firstname = userRep.getFirstname();
|
firstName = userRep.getFirstname();
|
||||||
if (StringHelper.isNotEmpty(userRep.getLastname()))
|
if (StringHelper.isNotEmpty(userRep.getLastname()))
|
||||||
lastname = userRep.getLastname();
|
lastName = userRep.getLastname();
|
||||||
if (userRep.getLocale() != null)
|
if (userRep.getLocale() != null)
|
||||||
locale = userRep.getLocale();
|
locale = userRep.getLocale();
|
||||||
if (userRep.getProperties() != null && !userRep.getProperties().isEmpty())
|
if (userRep.getProperties() != null && !userRep.getProperties().isEmpty())
|
||||||
propertyMap = userRep.getProperties();
|
propertyMap = userRep.getProperties();
|
||||||
|
|
||||||
// create new user
|
// create new user
|
||||||
User newUser = new User(userId, username, password, salt, firstname, lastname, userState, roles, locale,
|
User newUser = new User(userId, username, password, salt, hashAlgorithm, hashIterations, hashKeyLength,
|
||||||
propertyMap);
|
firstName, lastName, userState, roles, locale, propertyMap);
|
||||||
|
|
||||||
// detect privilege conflicts
|
// detect privilege conflicts
|
||||||
assertNoPrivilegeConflict(newUser);
|
assertNoPrivilegeConflict(newUser);
|
||||||
|
@ -656,7 +626,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
newRoles.add(roleName);
|
newRoles.add(roleName);
|
||||||
|
|
||||||
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), existingUser.getPassword(),
|
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), existingUser.getPassword(),
|
||||||
existingUser.getSalt(), existingUser.getFirstname(), existingUser.getLastname(),
|
existingUser.getSalt(), existingUser.getHashAlgorithm(), existingUser.getHashIterations(),
|
||||||
|
existingUser.getHashKeyLength(), existingUser.getFirstname(), existingUser.getLastname(),
|
||||||
existingUser.getUserState(), newRoles, existingUser.getLocale(), existingUser.getProperties());
|
existingUser.getUserState(), newRoles, existingUser.getLocale(), existingUser.getProperties());
|
||||||
|
|
||||||
// detect privilege conflicts
|
// detect privilege conflicts
|
||||||
|
@ -699,7 +670,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
Set<String> newRoles = new HashSet<>(currentRoles);
|
Set<String> newRoles = new HashSet<>(currentRoles);
|
||||||
newRoles.remove(roleName);
|
newRoles.remove(roleName);
|
||||||
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), existingUser.getPassword(),
|
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), existingUser.getPassword(),
|
||||||
existingUser.getSalt(), existingUser.getFirstname(), existingUser.getLastname(),
|
existingUser.getSalt(), existingUser.getHashAlgorithm(), existingUser.getHashIterations(),
|
||||||
|
existingUser.getHashKeyLength(), existingUser.getFirstname(), existingUser.getLastname(),
|
||||||
existingUser.getUserState(), newRoles, existingUser.getLocale(), existingUser.getProperties());
|
existingUser.getUserState(), newRoles, existingUser.getLocale(), existingUser.getProperties());
|
||||||
|
|
||||||
// delegate user replacement to persistence handler
|
// delegate user replacement to persistence handler
|
||||||
|
@ -725,7 +697,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
|
|
||||||
// create new user
|
// create new user
|
||||||
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), existingUser.getPassword(),
|
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), existingUser.getPassword(),
|
||||||
existingUser.getSalt(), existingUser.getFirstname(), existingUser.getLastname(),
|
existingUser.getSalt(), existingUser.getHashAlgorithm(), existingUser.getHashIterations(),
|
||||||
|
existingUser.getHashKeyLength(), existingUser.getFirstname(), existingUser.getLastname(),
|
||||||
existingUser.getUserState(), existingUser.getRoles(), locale, existingUser.getProperties());
|
existingUser.getUserState(), existingUser.getRoles(), locale, existingUser.getProperties());
|
||||||
|
|
||||||
// if the user is not setting their own locale, then make sure this user may set this user's locale
|
// if the user is not setting their own locale, then make sure this user may set this user's locale
|
||||||
|
@ -776,8 +749,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
|
|
||||||
// create new user
|
// create new user
|
||||||
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), passwordHash, salt,
|
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), passwordHash, salt,
|
||||||
existingUser.getFirstname(), existingUser.getLastname(), existingUser.getUserState(),
|
this.encryptionHandler.getAlgorithm(), this.encryptionHandler.getIterations(),
|
||||||
existingUser.getRoles(), existingUser.getLocale(), existingUser.getProperties());
|
this.encryptionHandler.getKeyLength(), existingUser.getFirstname(), existingUser.getLastname(),
|
||||||
|
existingUser.getUserState(), existingUser.getRoles(), existingUser.getLocale(),
|
||||||
|
existingUser.getProperties());
|
||||||
|
|
||||||
if (!certificate.getUsername().equals(username)) {
|
if (!certificate.getUsername().equals(username)) {
|
||||||
// check that the user may change their own password
|
// check that the user may change their own password
|
||||||
|
@ -819,7 +794,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
|
|
||||||
// create new user
|
// create new user
|
||||||
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), existingUser.getPassword(),
|
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), existingUser.getPassword(),
|
||||||
existingUser.getSalt(), existingUser.getFirstname(), existingUser.getLastname(), state,
|
existingUser.getSalt(), existingUser.getHashAlgorithm(), existingUser.getHashIterations(),
|
||||||
|
existingUser.getHashKeyLength(), existingUser.getFirstname(), existingUser.getLastname(), state,
|
||||||
existingUser.getRoles(), existingUser.getLocale(), existingUser.getProperties());
|
existingUser.getRoles(), existingUser.getLocale(), existingUser.getProperties());
|
||||||
|
|
||||||
// validate that this user may modify this user's state
|
// validate that this user may modify this user's state
|
||||||
|
@ -1300,18 +1276,53 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
throw new AccessDeniedException(
|
throw new AccessDeniedException(
|
||||||
MessageFormat.format("User {0} has no password and may not login!", username)); //$NON-NLS-1$
|
MessageFormat.format("User {0} has no password and may not login!", username)); //$NON-NLS-1$
|
||||||
byte[] salt = user.getSalt();
|
byte[] salt = user.getSalt();
|
||||||
if (salt == null)
|
|
||||||
throw new AccessDeniedException(
|
|
||||||
MessageFormat.format("User {0} has no salt and may not login!", username)); //$NON-NLS-1$
|
|
||||||
|
|
||||||
// we only work with hashed passwords
|
// we only work with hashed passwords
|
||||||
byte[] passwordHash = this.encryptionHandler.hashPassword(password, salt);
|
byte[] passwordHash;
|
||||||
|
if (salt == null) {
|
||||||
|
passwordHash = this.encryptionHandler.hashPasswordWithoutSalt(password);
|
||||||
|
} else if (user.getHashAlgorithm() == null || user.getHashIterations() == -1 || user.getHashKeyLength() == -1) {
|
||||||
|
passwordHash = this.encryptionHandler.hashPassword(password, salt);
|
||||||
|
} else {
|
||||||
|
passwordHash = this.encryptionHandler
|
||||||
|
.hashPassword(password, salt, user.getHashAlgorithm(), user.getHashIterations(),
|
||||||
|
user.getHashKeyLength());
|
||||||
|
}
|
||||||
|
|
||||||
// validate password
|
// validate password
|
||||||
if (!Arrays.equals(passwordHash, pwHash))
|
if (!Arrays.equals(passwordHash, pwHash))
|
||||||
throw new InvalidCredentialsException(
|
throw new InvalidCredentialsException(
|
||||||
MessageFormat.format("Password is incorrect for {0}", username)); //$NON-NLS-1$
|
MessageFormat.format("Password is incorrect for {0}", username)); //$NON-NLS-1$
|
||||||
|
|
||||||
|
// see if we need to update the hash
|
||||||
|
if (user.getHashAlgorithm() == null || user.getHashIterations() != this.encryptionHandler.getIterations()
|
||||||
|
|| user.getHashKeyLength() != this.encryptionHandler.getKeyLength()) {
|
||||||
|
|
||||||
|
logger.warn("Updating user " + username + " due to change in hashing algorithm properties ");
|
||||||
|
|
||||||
|
// get new salt for user
|
||||||
|
salt = this.encryptionHandler.nextSalt();
|
||||||
|
|
||||||
|
// hash password
|
||||||
|
passwordHash = this.encryptionHandler.hashPassword(password, salt);
|
||||||
|
|
||||||
|
// create new user
|
||||||
|
User newUser = new User(user.getUserId(), user.getUsername(), passwordHash, salt,
|
||||||
|
this.encryptionHandler.getAlgorithm(), this.encryptionHandler.getIterations(),
|
||||||
|
this.encryptionHandler.getKeyLength(), user.getFirstname(), user.getLastname(), user.getUserState(),
|
||||||
|
user.getRoles(), user.getLocale(), user.getProperties());
|
||||||
|
|
||||||
|
// delegate user replacement to persistence handler
|
||||||
|
this.persistenceHandler.replaceUser(newUser);
|
||||||
|
|
||||||
|
// perform automatic persisting, if enabled
|
||||||
|
if (this.autoPersistOnUserChangesData) {
|
||||||
|
this.persistenceHandler.persist();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Updated password for " + newUser.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1515,12 +1526,9 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
* @throws PrivilegeException
|
* @throws PrivilegeException
|
||||||
* if the this method is called multiple times or an initialization exception occurs
|
* if the this method is called multiple times or an initialization exception occurs
|
||||||
*/
|
*/
|
||||||
public synchronized void initialize(Map<String, String> parameterMap,
|
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||||
EncryptionHandler encryptionHandler,
|
PersistenceHandler persistenceHandler, UserChallengeHandler userChallengeHandler,
|
||||||
PersistenceHandler persistenceHandler,
|
SingleSignOnHandler ssoHandler, Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||||
UserChallengeHandler userChallengeHandler,
|
|
||||||
SingleSignOnHandler ssoHandler,
|
|
||||||
Map<String, Class<PrivilegePolicy>> policyMap) {
|
|
||||||
|
|
||||||
if (this.initialized)
|
if (this.initialized)
|
||||||
throw new PrivilegeException("Already initialized!"); //$NON-NLS-1$
|
throw new PrivilegeException("Already initialized!"); //$NON-NLS-1$
|
||||||
|
|
|
@ -69,6 +69,16 @@ public interface EncryptionHandler {
|
||||||
*/
|
*/
|
||||||
byte[] nextSalt();
|
byte[] nextSalt();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashes the given password configured algorithm
|
||||||
|
*
|
||||||
|
* @param password
|
||||||
|
* the password
|
||||||
|
*
|
||||||
|
* @return the hashed password
|
||||||
|
*/
|
||||||
|
byte[] hashPasswordWithoutSalt(final char[] password);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hashes the given password with the given salt with the configured algorithm
|
* Hashes the given password with the given salt with the configured algorithm
|
||||||
*
|
*
|
||||||
|
@ -81,6 +91,24 @@ public interface EncryptionHandler {
|
||||||
*/
|
*/
|
||||||
byte[] hashPassword(final char[] password, final byte[] salt);
|
byte[] hashPassword(final char[] password, final byte[] salt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashes the given password with the given salt and algorithm properties
|
||||||
|
*
|
||||||
|
* @param password
|
||||||
|
* the password
|
||||||
|
* @param salt
|
||||||
|
* the salt
|
||||||
|
* @param algorithm
|
||||||
|
* the algorithm
|
||||||
|
* @param iterations
|
||||||
|
* the iterations
|
||||||
|
* @param keyLength
|
||||||
|
* the keyLength
|
||||||
|
*
|
||||||
|
* @return the hashed password
|
||||||
|
*/
|
||||||
|
byte[] hashPassword(final char[] password, final byte[] salt, String algorithm, int iterations, int keyLength);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the concrete {@link EncryptionHandler}. The passed parameter map contains any configuration the
|
* Initialize the concrete {@link EncryptionHandler}. The passed parameter map contains any configuration the
|
||||||
* concrete {@link EncryptionHandler} might need
|
* concrete {@link EncryptionHandler} might need
|
||||||
|
|
|
@ -248,6 +248,11 @@ public class XmlConstants {
|
||||||
*/
|
*/
|
||||||
public static final String XML_PARAM_HASH_ALGORITHM = "hashAlgorithm";
|
public static final String XML_PARAM_HASH_ALGORITHM = "hashAlgorithm";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML_PARAM_HASH_ALGORITHM_NON_SALT = "hashAlgorithmNonSalt" :
|
||||||
|
*/
|
||||||
|
public static final String XML_PARAM_HASH_ALGORITHM_NON_SALT = "hashAlgorithmNonSalt";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XML_PARAM_HASH_ALGORITHM = "hashAlgorithm" :
|
* XML_PARAM_HASH_ALGORITHM = "hashAlgorithm" :
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -45,6 +45,9 @@ public final class User {
|
||||||
private final String username;
|
private final String username;
|
||||||
private final byte[] password;
|
private final byte[] password;
|
||||||
private final byte[] salt;
|
private final byte[] salt;
|
||||||
|
private final String hashAlgorithm;
|
||||||
|
private final int hashIterations;
|
||||||
|
private final int hashKeyLength;
|
||||||
|
|
||||||
private final String firstname;
|
private final String firstname;
|
||||||
private final String lastname;
|
private final String lastname;
|
||||||
|
@ -66,6 +69,14 @@ public final class User {
|
||||||
* the user's login name
|
* the user's login name
|
||||||
* @param password
|
* @param password
|
||||||
* the user's password (hashed)
|
* the user's password (hashed)
|
||||||
|
* @param salt
|
||||||
|
* the password salt
|
||||||
|
* @param hashAlgorithm
|
||||||
|
* the algorithm for the hash
|
||||||
|
* @param hashIterations
|
||||||
|
* the nr of iterations for hashing
|
||||||
|
* @param hashKeyLength
|
||||||
|
* the hash key length
|
||||||
* @param firstname
|
* @param firstname
|
||||||
* the user's first name
|
* the user's first name
|
||||||
* @param lastname
|
* @param lastname
|
||||||
|
@ -79,8 +90,9 @@ public final class User {
|
||||||
* @param propertyMap
|
* @param propertyMap
|
||||||
* a {@link Map} containing string value pairs of properties for this user
|
* a {@link Map} containing string value pairs of properties for this user
|
||||||
*/
|
*/
|
||||||
public User(String userId, String username, byte[] password, byte[] salt, String firstname, String lastname,
|
public User(String userId, String username, byte[] password, byte[] salt, String hashAlgorithm, int hashIterations,
|
||||||
UserState userState, Set<String> roles, Locale locale, Map<String, String> propertyMap) {
|
int hashKeyLength, String firstname, String lastname, UserState userState, Set<String> roles, Locale locale,
|
||||||
|
Map<String, String> propertyMap) {
|
||||||
|
|
||||||
if (StringHelper.isEmpty(userId)) {
|
if (StringHelper.isEmpty(userId)) {
|
||||||
throw new PrivilegeException("No UserId defined!"); //$NON-NLS-1$
|
throw new PrivilegeException("No UserId defined!"); //$NON-NLS-1$
|
||||||
|
@ -100,7 +112,7 @@ public final class User {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// password may be null, meaning not able to login
|
// password, salt and hash* may be null, meaning not able to login
|
||||||
// roles may be null, meaning not able to login and must be added later
|
// roles may be null, meaning not able to login and must be added later
|
||||||
// locale may be null, meaning use system default
|
// locale may be null, meaning use system default
|
||||||
// properties may be null, meaning no properties
|
// properties may be null, meaning no properties
|
||||||
|
@ -110,6 +122,11 @@ public final class User {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.salt = salt;
|
this.salt = salt;
|
||||||
|
|
||||||
|
this.hashAlgorithm = hashAlgorithm;
|
||||||
|
this.hashIterations = hashIterations;
|
||||||
|
this.hashKeyLength = hashKeyLength;
|
||||||
|
|
||||||
this.userState = userState;
|
this.userState = userState;
|
||||||
|
|
||||||
this.firstname = firstname;
|
this.firstname = firstname;
|
||||||
|
@ -163,6 +180,33 @@ public final class User {
|
||||||
return this.salt;
|
return this.salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the hash algorithm
|
||||||
|
*
|
||||||
|
* @return the hash algorithm
|
||||||
|
*/
|
||||||
|
public String getHashAlgorithm() {
|
||||||
|
return this.hashAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the hashIterations
|
||||||
|
*
|
||||||
|
* @return hashIterations
|
||||||
|
*/
|
||||||
|
public int getHashIterations() {
|
||||||
|
return this.hashIterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the hashKeyLength
|
||||||
|
*
|
||||||
|
* @return hashKeyLength
|
||||||
|
*/
|
||||||
|
public int getHashKeyLength() {
|
||||||
|
return this.hashKeyLength;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the first name
|
* @return the first name
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package li.strolch.privilege.xml;
|
package li.strolch.privilege.xml;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
@ -35,10 +36,6 @@ public class PrivilegeUsersDomWriter {
|
||||||
private List<User> users;
|
private List<User> users;
|
||||||
private File modelFile;
|
private File modelFile;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param users
|
|
||||||
* @param modelFile
|
|
||||||
*/
|
|
||||||
public PrivilegeUsersDomWriter(List<User> users, File modelFile) {
|
public PrivilegeUsersDomWriter(List<User> users, File modelFile) {
|
||||||
this.users = users;
|
this.users = users;
|
||||||
this.modelFile = modelFile;
|
this.modelFile = modelFile;
|
||||||
|
@ -51,7 +48,7 @@ public class PrivilegeUsersDomWriter {
|
||||||
Element rootElement = doc.createElement(XmlConstants.XML_USERS);
|
Element rootElement = doc.createElement(XmlConstants.XML_USERS);
|
||||||
doc.appendChild(rootElement);
|
doc.appendChild(rootElement);
|
||||||
|
|
||||||
this.users.stream().sorted((u1, u2) -> u1.getUserId().compareTo(u2.getUserId())).forEach(user -> {
|
this.users.stream().sorted(Comparator.comparing(User::getUserId)).forEach(user -> {
|
||||||
|
|
||||||
// create the user element
|
// create the user element
|
||||||
Element userElement = doc.createElement(XmlConstants.XML_USER);
|
Element userElement = doc.createElement(XmlConstants.XML_USER);
|
||||||
|
@ -59,10 +56,7 @@ public class PrivilegeUsersDomWriter {
|
||||||
|
|
||||||
userElement.setAttribute(XmlConstants.XML_ATTR_USER_ID, user.getUserId());
|
userElement.setAttribute(XmlConstants.XML_ATTR_USER_ID, user.getUserId());
|
||||||
userElement.setAttribute(XmlConstants.XML_ATTR_USERNAME, user.getUsername());
|
userElement.setAttribute(XmlConstants.XML_ATTR_USERNAME, user.getUsername());
|
||||||
if (user.getPassword() != null)
|
writePassword(user, userElement);
|
||||||
userElement.setAttribute(XmlConstants.XML_ATTR_PASSWORD, StringHelper.toHexString(user.getPassword()));
|
|
||||||
if (user.getSalt() != null)
|
|
||||||
userElement.setAttribute(XmlConstants.XML_ATTR_SALT, StringHelper.toHexString(user.getSalt()));
|
|
||||||
|
|
||||||
// add first name element
|
// add first name element
|
||||||
if (StringHelper.isNotEmpty(user.getFirstname())) {
|
if (StringHelper.isNotEmpty(user.getFirstname())) {
|
||||||
|
@ -113,4 +107,25 @@ public class PrivilegeUsersDomWriter {
|
||||||
// write the container file to disk
|
// write the container file to disk
|
||||||
XmlHelper.writeDocument(doc, this.modelFile);
|
XmlHelper.writeDocument(doc, this.modelFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writePassword(User user, Element userElement) {
|
||||||
|
|
||||||
|
if (user.getPassword() != null && user.getSalt() != null && user.getHashAlgorithm() != null
|
||||||
|
&& user.getHashIterations() != -1 && user.getHashKeyLength() != -1) {
|
||||||
|
|
||||||
|
String algo = user.getHashAlgorithm() + "," + user.getHashIterations() + "," + user.getHashKeyLength();
|
||||||
|
String hash = StringHelper.toHexString(user.getSalt());
|
||||||
|
String password = StringHelper.toHexString(user.getPassword());
|
||||||
|
|
||||||
|
String passwordS = "$" + algo + "$" + hash + "$" + password;
|
||||||
|
userElement.setAttribute(XmlConstants.XML_ATTR_PASSWORD, passwordS);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (user.getPassword() != null)
|
||||||
|
userElement.setAttribute(XmlConstants.XML_ATTR_PASSWORD, StringHelper.toHexString(user.getPassword()));
|
||||||
|
if (user.getSalt() != null)
|
||||||
|
userElement.setAttribute(XmlConstants.XML_ATTR_SALT, StringHelper.toHexString(user.getSalt()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,9 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
||||||
String username;
|
String username;
|
||||||
byte[] password;
|
byte[] password;
|
||||||
byte[] salt;
|
byte[] salt;
|
||||||
|
String hashAlgorithm;
|
||||||
|
int hashIterations = -1;
|
||||||
|
int hashKeyLength = -1;
|
||||||
String firstName;
|
String firstName;
|
||||||
String lastname;
|
String lastname;
|
||||||
UserState userState;
|
UserState userState;
|
||||||
|
@ -137,12 +140,46 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
||||||
if (qName.equals(XmlConstants.XML_USER)) {
|
if (qName.equals(XmlConstants.XML_USER)) {
|
||||||
this.userId = attributes.getValue(XmlConstants.XML_ATTR_USER_ID);
|
this.userId = attributes.getValue(XmlConstants.XML_ATTR_USER_ID);
|
||||||
this.username = attributes.getValue(XmlConstants.XML_ATTR_USERNAME);
|
this.username = attributes.getValue(XmlConstants.XML_ATTR_USERNAME);
|
||||||
String passwordS = attributes.getValue(XmlConstants.XML_ATTR_PASSWORD);
|
|
||||||
if (!StringHelper.isEmpty(passwordS))
|
String password = attributes.getValue(XmlConstants.XML_ATTR_PASSWORD);
|
||||||
|
String salt = attributes.getValue(XmlConstants.XML_ATTR_SALT);
|
||||||
|
parsePassword(password, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parsePassword(String passwordS, String salt) {
|
||||||
|
|
||||||
|
if (StringHelper.isNotEmpty(salt))
|
||||||
|
this.salt = StringHelper.fromHexString(salt);
|
||||||
|
|
||||||
|
if (StringHelper.isEmpty(passwordS))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!passwordS.startsWith("$")) {
|
||||||
this.password = StringHelper.fromHexString(passwordS);
|
this.password = StringHelper.fromHexString(passwordS);
|
||||||
String saltS = attributes.getValue(XmlConstants.XML_ATTR_SALT);
|
} else {
|
||||||
if (!StringHelper.isEmpty(saltS))
|
|
||||||
this.salt = StringHelper.fromHexString(saltS);
|
String[] parts = passwordS.split("\\$");
|
||||||
|
if (parts.length != 4) {
|
||||||
|
logger.error("Illegal password " + passwordS + ": Starts with $, but does not have 3 parts!");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
String hashAlgorithm = parts[1];
|
||||||
|
String[] hashParts = hashAlgorithm.split(",");
|
||||||
|
|
||||||
|
if (hashParts.length != 3) {
|
||||||
|
logger.error("Illegal password " + passwordS
|
||||||
|
+ ": hashAlgorithm part does not have 3 parts separated by comma!");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this.hashAlgorithm = hashParts[0];
|
||||||
|
this.hashIterations = Integer.parseInt(hashParts[1]);
|
||||||
|
this.hashKeyLength = Integer.parseInt(hashParts[2]);
|
||||||
|
|
||||||
|
this.salt = StringHelper.fromHexString(parts[2]);
|
||||||
|
this.password = StringHelper.fromHexString(parts[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,31 +191,52 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
||||||
@Override
|
@Override
|
||||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||||
|
|
||||||
if (qName.equals(XmlConstants.XML_FIRSTNAME)) {
|
switch (qName) {
|
||||||
this.firstName = this.text.toString().trim();
|
case XmlConstants.XML_FIRSTNAME:
|
||||||
} else if (qName.equals(XmlConstants.XML_LASTNAME)) {
|
|
||||||
this.lastname = this.text.toString().trim();
|
|
||||||
} else if (qName.equals(XmlConstants.XML_STATE)) {
|
|
||||||
this.userState = UserState.valueOf(this.text.toString().trim());
|
|
||||||
} else if (qName.equals(XmlConstants.XML_LOCALE)) {
|
|
||||||
this.locale = new Locale(this.text.toString().trim());
|
|
||||||
} else if (qName.equals(XmlConstants.XML_ROLE)) {
|
|
||||||
this.userRoles.add(this.text.toString().trim());
|
|
||||||
} else if (qName.equals(XmlConstants.XML_ROLES)) {
|
|
||||||
// NO-OP
|
|
||||||
} else if (qName.equals(XmlConstants.XML_PARAMETER)) {
|
|
||||||
// NO-OP
|
|
||||||
} else if (qName.equals(XmlConstants.XML_PARAMETERS)) {
|
|
||||||
// NO-OP
|
|
||||||
} else if (qName.equals(XmlConstants.XML_USER)) {
|
|
||||||
|
|
||||||
User user = new User(this.userId, this.username, this.password, this.salt, this.firstName,
|
this.firstName = this.text.toString().trim();
|
||||||
this.lastname, this.userState, this.userRoles, this.locale, this.parameters);
|
break;
|
||||||
|
|
||||||
|
case XmlConstants.XML_LASTNAME:
|
||||||
|
|
||||||
|
this.lastname = this.text.toString().trim();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlConstants.XML_STATE:
|
||||||
|
|
||||||
|
this.userState = UserState.valueOf(this.text.toString().trim());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlConstants.XML_LOCALE:
|
||||||
|
|
||||||
|
this.locale = new Locale(this.text.toString().trim());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlConstants.XML_ROLE:
|
||||||
|
|
||||||
|
this.userRoles.add(this.text.toString().trim());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlConstants.XML_USER:
|
||||||
|
|
||||||
|
User user = new User(this.userId, this.username, this.password, this.salt, this.hashAlgorithm,
|
||||||
|
hashIterations, hashKeyLength, this.firstName, this.lastname, this.userState, this.userRoles,
|
||||||
|
this.locale, this.parameters);
|
||||||
logger.info(MessageFormat.format("New User: {0}", user)); //$NON-NLS-1$
|
logger.info(MessageFormat.format("New User: {0}", user)); //$NON-NLS-1$
|
||||||
|
|
||||||
getUsers().add(user);
|
getUsers().add(user);
|
||||||
} else {
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
if (!(qName.equals(XmlConstants.XML_ROLES) //
|
||||||
|
|| qName.equals(XmlConstants.XML_PARAMETER) //
|
||||||
|
|| qName.equals(XmlConstants.XML_PARAMETERS))) {
|
||||||
throw new IllegalArgumentException("Unhandled tag " + qName);
|
throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -198,16 +256,22 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
||||||
@Override
|
@Override
|
||||||
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||||
throws SAXException {
|
throws SAXException {
|
||||||
if (qName.equals(XmlConstants.XML_PROPERTY)) {
|
|
||||||
|
switch (qName) {
|
||||||
|
case XmlConstants.XML_PROPERTY:
|
||||||
|
|
||||||
String key = attributes.getValue(XmlConstants.XML_ATTR_NAME);
|
String key = attributes.getValue(XmlConstants.XML_ATTR_NAME);
|
||||||
String value = attributes.getValue(XmlConstants.XML_ATTR_VALUE);
|
String value = attributes.getValue(XmlConstants.XML_ATTR_VALUE);
|
||||||
this.parameterMap.put(key, value);
|
this.parameterMap.put(key, value);
|
||||||
} else if (qName.equals(XmlConstants.XML_PROPERTIES)) {
|
break;
|
||||||
// NO-OP
|
|
||||||
} else {
|
default:
|
||||||
|
|
||||||
|
if (!qName.equals(XmlConstants.XML_PROPERTIES)) {
|
||||||
throw new IllegalArgumentException("Unhandled tag " + qName);
|
throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String, String> getParameterMap() {
|
public Map<String, String> getParameterMap() {
|
||||||
return this.parameterMap;
|
return this.parameterMap;
|
||||||
|
|
|
@ -70,6 +70,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
|
||||||
private static final String ROLE_PRIVILEGE_ADMIN = "PrivilegeAdmin";
|
private static final String ROLE_PRIVILEGE_ADMIN = "PrivilegeAdmin";
|
||||||
private static final String PRIVILEGE_USER_ACCESS = "UserAccessPrivilege";
|
private static final String PRIVILEGE_USER_ACCESS = "UserAccessPrivilege";
|
||||||
private static final String ADMIN = "admin";
|
private static final String ADMIN = "admin";
|
||||||
|
private static final String ADMIN2 = "admin2";
|
||||||
private static final char[] PASS_ADMIN = "admin".toCharArray();
|
private static final char[] PASS_ADMIN = "admin".toCharArray();
|
||||||
private static final String BOB = "bob";
|
private static final String BOB = "bob";
|
||||||
private static final String TED = "ted";
|
private static final String TED = "ted";
|
||||||
|
@ -117,6 +118,15 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAuthenticationAdmin2Ok() throws Exception {
|
||||||
|
try {
|
||||||
|
login(ADMIN2, ArraysHelper.copyOf(PASS_ADMIN));
|
||||||
|
} finally {
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFailAuthenticationNOk() throws Exception {
|
public void testFailAuthenticationNOk() throws Exception {
|
||||||
this.exception.expect(AccessDeniedException.class);
|
this.exception.expect(AccessDeniedException.class);
|
||||||
|
@ -328,7 +338,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
|
||||||
UserRep selectorRep = new UserRep(null, null, null, null, null,
|
UserRep selectorRep = new UserRep(null, null, null, null, null,
|
||||||
new HashSet<>(Collections.singletonList("PrivilegeAdmin")), null, null);
|
new HashSet<>(Collections.singletonList("PrivilegeAdmin")), null, null);
|
||||||
List<UserRep> users = this.privilegeHandler.queryUsers(certificate, selectorRep);
|
List<UserRep> users = this.privilegeHandler.queryUsers(certificate, selectorRep);
|
||||||
assertEquals(1, users.size());
|
assertEquals(2, users.size());
|
||||||
assertEquals(ADMIN, users.get(0).getUsername());
|
assertEquals(ADMIN, users.get(0).getUsername());
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -36,7 +36,6 @@ import li.strolch.privilege.xml.*;
|
||||||
import li.strolch.utils.helper.FileHelper;
|
import li.strolch.utils.helper.FileHelper;
|
||||||
import li.strolch.utils.helper.StringHelper;
|
import li.strolch.utils.helper.StringHelper;
|
||||||
import li.strolch.utils.helper.XmlHelper;
|
import li.strolch.utils.helper.XmlHelper;
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -52,23 +51,19 @@ public class XmlTest {
|
||||||
private static final String SRC_TEST = "src/test/resources/config/";
|
private static final String SRC_TEST = "src/test/resources/config/";
|
||||||
private static final Logger logger = LoggerFactory.getLogger(XmlTest.class);
|
private static final Logger logger = LoggerFactory.getLogger(XmlTest.class);
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws Exception
|
|
||||||
* if something goes wrong
|
|
||||||
*/
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void init() throws Exception {
|
public static void init() {
|
||||||
|
|
||||||
cleanUp();
|
cleanUp();
|
||||||
|
|
||||||
File tmpDir = new File("target/test");
|
File tmpDir = new File("target/test");
|
||||||
if (tmpDir.exists())
|
if (tmpDir.exists())
|
||||||
FileHelper.deleteFile(tmpDir, false);
|
FileHelper.deleteFile(tmpDir, false);
|
||||||
tmpDir.mkdirs();
|
if (!tmpDir.mkdirs())
|
||||||
|
throw new IllegalStateException("Could not create temp dir " + tmpDir.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
public static void cleanUp() {
|
||||||
public static void cleanUp() throws Exception {
|
|
||||||
|
|
||||||
File tmpDir = new File("target/test");
|
File tmpDir = new File("target/test");
|
||||||
if (!tmpDir.exists())
|
if (!tmpDir.exists())
|
||||||
|
@ -161,7 +156,7 @@ public class XmlTest {
|
||||||
List<User> users = xmlHandler.getUsers();
|
List<User> users = xmlHandler.getUsers();
|
||||||
assertNotNull(users);
|
assertNotNull(users);
|
||||||
|
|
||||||
assertEquals(3, users.size());
|
assertEquals(4, users.size());
|
||||||
|
|
||||||
//
|
//
|
||||||
// users
|
// users
|
||||||
|
@ -319,15 +314,15 @@ public class XmlTest {
|
||||||
propertyMap.put("prop1", "value1");
|
propertyMap.put("prop1", "value1");
|
||||||
userRoles = new HashSet<>();
|
userRoles = new HashSet<>();
|
||||||
userRoles.add("role1");
|
userRoles.add("role1");
|
||||||
User user1 = new User("1", "user1", "blabla".getBytes(), "blabla".getBytes(), "Bob", "White",
|
User user1 = new User("1", "user1", "blabla".getBytes(), "blabla".getBytes(), "PBKDF2WithHmacSHA512", 10000,
|
||||||
UserState.DISABLED, userRoles, Locale.ENGLISH, propertyMap);
|
256, "Bob", "White", UserState.DISABLED, userRoles, Locale.ENGLISH, propertyMap);
|
||||||
users.add(user1);
|
users.add(user1);
|
||||||
|
|
||||||
propertyMap = new HashMap<>();
|
propertyMap = new HashMap<>();
|
||||||
propertyMap.put("prop2", "value2");
|
propertyMap.put("prop2", "value2");
|
||||||
userRoles = new HashSet<>();
|
userRoles = new HashSet<>();
|
||||||
userRoles.add("role2");
|
userRoles.add("role2");
|
||||||
User user2 = new User("2", "user2", "haha".getBytes(), "haha".getBytes(), "Leonard", "Sheldon",
|
User user2 = new User("2", "user2", "haha".getBytes(), "haha".getBytes(), null, -1, -1, "Leonard", "Sheldon",
|
||||||
UserState.ENABLED, userRoles, Locale.ENGLISH, propertyMap);
|
UserState.ENABLED, userRoles, Locale.ENGLISH, propertyMap);
|
||||||
users.add(user2);
|
users.add(user2);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class DummySsoHandler implements SingleSignOnHandler {
|
||||||
|
|
||||||
Set<String> roles = Arrays.stream(map.get("roles").split(",")).map(String::trim).collect(Collectors.toSet());
|
Set<String> roles = Arrays.stream(map.get("roles").split(",")).map(String::trim).collect(Collectors.toSet());
|
||||||
Map<String, String> properties = new HashMap<>();
|
Map<String, String> properties = new HashMap<>();
|
||||||
return new User(map.get("userId"), map.get("username"), null, null, map.get("firstName"), map.get("lastName"),
|
return new User(map.get("userId"), map.get("username"), null, null, null, -1, -1, map.get("firstName"),
|
||||||
UserState.ENABLED, roles, Locale.ENGLISH, properties);
|
map.get("lastName"), UserState.ENABLED, roles, Locale.ENGLISH, properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,22 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Users>
|
<Users>
|
||||||
|
|
||||||
<User userId="1" username="admin" password="cb69962946617da006a2f95776d78b49e5ec7941d2bdb2d25cdb05f957f64344" salt="61646d696e">
|
<User userId="1" username="admin" password="$PBKDF2WithHmacSHA512,10000,256$61646d696e$cb69962946617da006a2f95776d78b49e5ec7941d2bdb2d25cdb05f957f64344">
|
||||||
|
<Firstname>Application</Firstname>
|
||||||
|
<Lastname>Administrator</Lastname>
|
||||||
|
<State>ENABLED</State>
|
||||||
|
<Locale>en_GB</Locale>
|
||||||
|
<Roles>
|
||||||
|
<Role>PrivilegeAdmin</Role>
|
||||||
|
<Role>AppUser</Role>
|
||||||
|
</Roles>
|
||||||
|
<Properties>
|
||||||
|
<Property name="organization" value="eitchnet.ch"/>
|
||||||
|
<Property name="organizationalUnit" value="Development"/>
|
||||||
|
</Properties>
|
||||||
|
</User>
|
||||||
|
|
||||||
|
<User userId="1" username="admin2" password="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918">
|
||||||
<Firstname>Application</Firstname>
|
<Firstname>Application</Firstname>
|
||||||
<Lastname>Administrator</Lastname>
|
<Lastname>Administrator</Lastname>
|
||||||
<State>ENABLED</State>
|
<State>ENABLED</State>
|
||||||
|
|
Loading…
Reference in New Issue