[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 static final String DEFAULT_ALGORITHM_NON_SALT = "SHA-256";
|
||||
public static final String DEFAULT_ALGORITHM = "PBKDF2WithHmacSHA512";
|
||||
public static final int DEFAULT_KEY_LENGTH = 256;
|
||||
public static final int DEFAULT_SMALL_ITERATIONS = 10000;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -15,9 +15,7 @@
|
|||
*/
|
||||
package li.strolch.privilege.handler;
|
||||
|
||||
import static li.strolch.privilege.base.PrivilegeConstants.DEFAULT_ALGORITHM;
|
||||
import static li.strolch.privilege.base.PrivilegeConstants.DEFAULT_ITERATIONS;
|
||||
import static li.strolch.privilege.base.PrivilegeConstants.DEFAULT_KEY_LENGTH;
|
||||
import static li.strolch.privilege.base.PrivilegeConstants.*;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
|
@ -61,6 +59,11 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
|
|||
*/
|
||||
private SecureRandom secureRandom;
|
||||
|
||||
/**
|
||||
* The non-salt algorithm for this instance
|
||||
*/
|
||||
private String nonSaltAlgorithm;
|
||||
|
||||
/**
|
||||
* The configured algorithm for this instance
|
||||
*/
|
||||
|
@ -110,12 +113,30 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
|
|||
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
|
||||
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 {
|
||||
SecretKeyFactory skf = SecretKeyFactory.getInstance(this.algorithm);
|
||||
PBEKeySpec spec = new PBEKeySpec(password, salt, this.iterations, this.keyLength);
|
||||
SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
|
||||
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, keyLength);
|
||||
SecretKey key = skf.generateSecret(spec);
|
||||
return key.getEncoded();
|
||||
|
||||
|
@ -131,11 +152,26 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
|
|||
|
||||
// get hash algorithm parameters
|
||||
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(
|
||||
parameterMap.getOrDefault(XmlConstants.XML_PARAM_HASH_ITERATIONS, String.valueOf(DEFAULT_ITERATIONS)));
|
||||
this.keyLength = Integer.parseInt(
|
||||
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
|
||||
try {
|
||||
hashPassword("test".toCharArray(), "test".getBytes()); //$NON-NLS-1$
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -204,8 +204,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
}
|
||||
});
|
||||
|
||||
List<RoleRep> roles = rolesStream.map(Role::asRoleRep).collect(Collectors.toList());
|
||||
return roles;
|
||||
return rolesStream.map(Role::asRoleRep).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -228,8 +227,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
}
|
||||
});
|
||||
|
||||
List<UserRep> users = usersStream.map(User::asUserRep).collect(Collectors.toList());
|
||||
return users;
|
||||
return usersStream.map(User::asUserRep).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -241,8 +239,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
String selUserId = selectorRep.getUserId();
|
||||
String selUsername = selectorRep.getUsername();
|
||||
String selFirstname = selectorRep.getFirstname();
|
||||
String selLastname = selectorRep.getLastname();
|
||||
String selFirstName = selectorRep.getFirstname();
|
||||
String selLastName = selectorRep.getLastname();
|
||||
UserState selUserState = selectorRep.getUserState();
|
||||
Locale selLocale = selectorRep.getLocale();
|
||||
Set<String> selRoles = selectorRep.getRoles();
|
||||
|
@ -262,60 +260,30 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
// selections
|
||||
boolean userIdSelected;
|
||||
boolean usernameSelected;
|
||||
boolean firstnameSelected;
|
||||
boolean lastnameSelected;
|
||||
boolean firstNameSelected;
|
||||
boolean lastNameSelected;
|
||||
boolean userStateSelected;
|
||||
boolean localeSelected;
|
||||
boolean roleSelected;
|
||||
boolean propertySelected;
|
||||
|
||||
// userId
|
||||
if (selUserId == null)
|
||||
userIdSelected = true;
|
||||
else if (selUserId.equals(user.getUserId()))
|
||||
userIdSelected = true;
|
||||
else
|
||||
userIdSelected = false;
|
||||
userIdSelected = selUserId == null || selUserId.equals(user.getUserId());
|
||||
|
||||
// username
|
||||
if (selUsername == null)
|
||||
usernameSelected = true;
|
||||
else if (selUsername.equals(user.getUsername()))
|
||||
usernameSelected = true;
|
||||
else
|
||||
usernameSelected = false;
|
||||
usernameSelected = selUsername == null || selUsername.equals(user.getUsername());
|
||||
|
||||
// firstname
|
||||
if (selFirstname == null)
|
||||
firstnameSelected = true;
|
||||
else if (selFirstname.equals(user.getFirstname()))
|
||||
firstnameSelected = true;
|
||||
else
|
||||
firstnameSelected = false;
|
||||
firstNameSelected = selFirstName == null || selFirstName.equals(user.getFirstname());
|
||||
|
||||
// lastname
|
||||
if (selLastname == null)
|
||||
lastnameSelected = true;
|
||||
else if (selLastname.equals(user.getLastname()))
|
||||
lastnameSelected = true;
|
||||
else
|
||||
lastnameSelected = false;
|
||||
lastNameSelected = selLastName == null || selLastName.equals(user.getLastname());
|
||||
|
||||
// user state
|
||||
if (selUserState == null)
|
||||
userStateSelected = true;
|
||||
else if (selUserState.equals(user.getUserState()))
|
||||
userStateSelected = true;
|
||||
else
|
||||
userStateSelected = false;
|
||||
userStateSelected = selUserState == null || selUserState.equals(user.getUserState());
|
||||
|
||||
// locale
|
||||
if (selLocale == null)
|
||||
localeSelected = true;
|
||||
else if (selLocale.equals(user.getLocale()))
|
||||
localeSelected = true;
|
||||
else
|
||||
localeSelected = false;
|
||||
localeSelected = selLocale == null || selLocale.equals(user.getLocale());
|
||||
|
||||
// roles
|
||||
roleSelected = isSelectedByRole(selRoles, user.getRoles());
|
||||
|
@ -324,7 +292,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
propertySelected = isSelectedByProperty(selPropertyMap, user.getProperties());
|
||||
|
||||
boolean selected =
|
||||
userIdSelected && usernameSelected && firstnameSelected && lastnameSelected && userStateSelected
|
||||
userIdSelected && usernameSelected && firstNameSelected && lastNameSelected && userStateSelected
|
||||
&& localeSelected && roleSelected && propertySelected;
|
||||
|
||||
if (selected)
|
||||
|
@ -378,11 +346,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
* null or empty, then true is returned, otherwise false
|
||||
*/
|
||||
private boolean isSelectedByRole(Set<String> selectionRoles, Set<String> roles) {
|
||||
|
||||
if (selectionRoles == null)
|
||||
return true;
|
||||
|
||||
return roles.containsAll(selectionRoles);
|
||||
return selectionRoles == null || roles.containsAll(selectionRoles);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -531,7 +495,9 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
Set<String> roles = userRep.getRoles();
|
||||
Locale locale = userRep.getLocale();
|
||||
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
|
||||
|
@ -562,26 +528,30 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
String username = existingUser.getUsername();
|
||||
byte[] password = existingUser.getPassword();
|
||||
byte[] salt = existingUser.getSalt();
|
||||
String firstname = existingUser.getFirstname();
|
||||
String lastname = existingUser.getLastname();
|
||||
String firstName = existingUser.getFirstname();
|
||||
String lastName = existingUser.getLastname();
|
||||
UserState userState = existingUser.getUserState();
|
||||
Set<String> roles = existingUser.getRoles();
|
||||
Locale locale = existingUser.getLocale();
|
||||
Map<String, String> propertyMap = existingUser.getProperties();
|
||||
|
||||
String hashAlgorithm = existingUser.getHashAlgorithm();
|
||||
int hashIterations = existingUser.getHashIterations();
|
||||
int hashKeyLength = existingUser.getHashKeyLength();
|
||||
|
||||
// get updated fields
|
||||
if (StringHelper.isNotEmpty(userRep.getFirstname()))
|
||||
firstname = userRep.getFirstname();
|
||||
firstName = userRep.getFirstname();
|
||||
if (StringHelper.isNotEmpty(userRep.getLastname()))
|
||||
lastname = userRep.getLastname();
|
||||
lastName = userRep.getLastname();
|
||||
if (userRep.getLocale() != null)
|
||||
locale = userRep.getLocale();
|
||||
if (userRep.getProperties() != null && !userRep.getProperties().isEmpty())
|
||||
propertyMap = userRep.getProperties();
|
||||
|
||||
// create new user
|
||||
User newUser = new User(userId, username, password, salt, firstname, lastname, userState, roles, locale,
|
||||
propertyMap);
|
||||
User newUser = new User(userId, username, password, salt, hashAlgorithm, hashIterations, hashKeyLength,
|
||||
firstName, lastName, userState, roles, locale, propertyMap);
|
||||
|
||||
// detect privilege conflicts
|
||||
assertNoPrivilegeConflict(newUser);
|
||||
|
@ -656,7 +626,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
newRoles.add(roleName);
|
||||
|
||||
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());
|
||||
|
||||
// detect privilege conflicts
|
||||
|
@ -699,7 +670,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
Set<String> newRoles = new HashSet<>(currentRoles);
|
||||
newRoles.remove(roleName);
|
||||
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());
|
||||
|
||||
// delegate user replacement to persistence handler
|
||||
|
@ -725,7 +697,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
// create new user
|
||||
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());
|
||||
|
||||
// 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
|
||||
User newUser = new User(existingUser.getUserId(), existingUser.getUsername(), passwordHash, salt,
|
||||
existingUser.getFirstname(), existingUser.getLastname(), existingUser.getUserState(),
|
||||
existingUser.getRoles(), existingUser.getLocale(), existingUser.getProperties());
|
||||
this.encryptionHandler.getAlgorithm(), this.encryptionHandler.getIterations(),
|
||||
this.encryptionHandler.getKeyLength(), existingUser.getFirstname(), existingUser.getLastname(),
|
||||
existingUser.getUserState(), existingUser.getRoles(), existingUser.getLocale(),
|
||||
existingUser.getProperties());
|
||||
|
||||
if (!certificate.getUsername().equals(username)) {
|
||||
// check that the user may change their own password
|
||||
|
@ -819,7 +794,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
// create new user
|
||||
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());
|
||||
|
||||
// validate that this user may modify this user's state
|
||||
|
@ -1300,18 +1276,53 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
throw new AccessDeniedException(
|
||||
MessageFormat.format("User {0} has no password and may not login!", username)); //$NON-NLS-1$
|
||||
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
|
||||
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
|
||||
if (!Arrays.equals(passwordHash, pwHash))
|
||||
throw new InvalidCredentialsException(
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1515,12 +1526,9 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
* @throws PrivilegeException
|
||||
* 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) {
|
||||
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||
PersistenceHandler persistenceHandler, UserChallengeHandler userChallengeHandler,
|
||||
SingleSignOnHandler ssoHandler, Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
|
||||
if (this.initialized)
|
||||
throw new PrivilegeException("Already initialized!"); //$NON-NLS-1$
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -69,6 +69,16 @@ public interface EncryptionHandler {
|
|||
*/
|
||||
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
|
||||
*
|
||||
|
@ -81,6 +91,24 @@ public interface EncryptionHandler {
|
|||
*/
|
||||
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
|
||||
* concrete {@link EncryptionHandler} might need
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -17,7 +17,7 @@ package li.strolch.privilege.helper;
|
|||
|
||||
/**
|
||||
* The constants used in parsing XML documents which contain the configuration for Privilege
|
||||
*
|
||||
*
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
|
@ -248,6 +248,11 @@ public class XmlConstants {
|
|||
*/
|
||||
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" :
|
||||
*/
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -30,12 +30,12 @@ import li.strolch.utils.helper.StringHelper;
|
|||
/**
|
||||
* This class defines the actual login information for a given user which can be granted privileges. Every user is
|
||||
* granted a set of {@link Role}s and has a {@link UserState} including detail information like first name and lastname
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Note: This is an internal object which is not to be serialized or passed to clients, {@link UserRep}s are used for
|
||||
* that
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public final class User {
|
||||
|
@ -45,6 +45,9 @@ public final class User {
|
|||
private final String username;
|
||||
private final byte[] password;
|
||||
private final byte[] salt;
|
||||
private final String hashAlgorithm;
|
||||
private final int hashIterations;
|
||||
private final int hashKeyLength;
|
||||
|
||||
private final String firstname;
|
||||
private final String lastname;
|
||||
|
@ -59,28 +62,37 @@ public final class User {
|
|||
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
*
|
||||
* @param userId
|
||||
* the user's id
|
||||
* the user's id
|
||||
* @param username
|
||||
* the user's login name
|
||||
* the user's login name
|
||||
* @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
|
||||
* the user's first name
|
||||
* the user's first name
|
||||
* @param lastname
|
||||
* the user's lastname
|
||||
* the user's lastname
|
||||
* @param userState
|
||||
* the user's {@link UserState}
|
||||
* the user's {@link UserState}
|
||||
* @param roles
|
||||
* the set of {@link Role}s assigned to this user
|
||||
* the set of {@link Role}s assigned to this user
|
||||
* @param locale
|
||||
* the user's {@link Locale}
|
||||
* the user's {@link Locale}
|
||||
* @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,
|
||||
UserState userState, Set<String> roles, Locale locale, Map<String, String> propertyMap) {
|
||||
public User(String userId, String username, byte[] password, byte[] salt, String hashAlgorithm, int hashIterations,
|
||||
int hashKeyLength, String firstname, String lastname, UserState userState, Set<String> roles, Locale locale,
|
||||
Map<String, String> propertyMap) {
|
||||
|
||||
if (StringHelper.isEmpty(userId)) {
|
||||
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
|
||||
// locale may be null, meaning use system default
|
||||
// properties may be null, meaning no properties
|
||||
|
@ -110,6 +122,11 @@ public final class User {
|
|||
this.username = username;
|
||||
this.password = password;
|
||||
this.salt = salt;
|
||||
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.hashIterations = hashIterations;
|
||||
this.hashKeyLength = hashKeyLength;
|
||||
|
||||
this.userState = userState;
|
||||
|
||||
this.firstname = firstname;
|
||||
|
@ -147,7 +164,7 @@ public final class User {
|
|||
|
||||
/**
|
||||
* Returns the hashed password for this {@link User}
|
||||
*
|
||||
*
|
||||
* @return the hashed password for this {@link User}
|
||||
*/
|
||||
public byte[] getPassword() {
|
||||
|
@ -156,13 +173,40 @@ public final class User {
|
|||
|
||||
/**
|
||||
* Return the salt for this {@link User}
|
||||
*
|
||||
*
|
||||
* @return the salt for this {@link User}
|
||||
*/
|
||||
public byte[] getSalt() {
|
||||
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
|
||||
*/
|
||||
|
@ -193,10 +237,10 @@ public final class User {
|
|||
|
||||
/**
|
||||
* Returns true if this user has the specified role
|
||||
*
|
||||
*
|
||||
* @param role
|
||||
* the name of the {@link Role} to check for
|
||||
*
|
||||
* the name of the {@link Role} to check for
|
||||
*
|
||||
* @return true if the this user has the specified role
|
||||
*/
|
||||
public boolean hasRole(String role) {
|
||||
|
@ -212,10 +256,10 @@ public final class User {
|
|||
|
||||
/**
|
||||
* Returns the property with the given key
|
||||
*
|
||||
*
|
||||
* @param key
|
||||
* the key for which the property is to be returned
|
||||
*
|
||||
* the key for which the property is to be returned
|
||||
*
|
||||
* @return the property with the given key, or null if the property is not defined
|
||||
*/
|
||||
public String getProperty(String key) {
|
||||
|
@ -224,7 +268,7 @@ public final class User {
|
|||
|
||||
/**
|
||||
* Returns the {@link Set} of keys of all properties
|
||||
*
|
||||
*
|
||||
* @return the {@link Set} of keys of all properties
|
||||
*/
|
||||
public Set<String> getPropertyKeySet() {
|
||||
|
@ -233,7 +277,7 @@ public final class User {
|
|||
|
||||
/**
|
||||
* Returns the map of properties
|
||||
*
|
||||
*
|
||||
* @return the map of properties
|
||||
*/
|
||||
public Map<String, String> getProperties() {
|
||||
|
@ -250,7 +294,7 @@ public final class User {
|
|||
|
||||
/**
|
||||
* Returns a string representation of this object displaying its concrete type and its values
|
||||
*
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@SuppressWarnings("nls")
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -16,6 +16,7 @@
|
|||
package li.strolch.privilege.xml;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
|
@ -35,10 +36,6 @@ public class PrivilegeUsersDomWriter {
|
|||
private List<User> users;
|
||||
private File modelFile;
|
||||
|
||||
/**
|
||||
* @param users
|
||||
* @param modelFile
|
||||
*/
|
||||
public PrivilegeUsersDomWriter(List<User> users, File modelFile) {
|
||||
this.users = users;
|
||||
this.modelFile = modelFile;
|
||||
|
@ -51,7 +48,7 @@ public class PrivilegeUsersDomWriter {
|
|||
Element rootElement = doc.createElement(XmlConstants.XML_USERS);
|
||||
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
|
||||
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_USERNAME, user.getUsername());
|
||||
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()));
|
||||
writePassword(user, userElement);
|
||||
|
||||
// add first name element
|
||||
if (StringHelper.isNotEmpty(user.getFirstname())) {
|
||||
|
@ -113,4 +107,25 @@ public class PrivilegeUsersDomWriter {
|
|||
// write the container file to disk
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -117,6 +117,9 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
String username;
|
||||
byte[] password;
|
||||
byte[] salt;
|
||||
String hashAlgorithm;
|
||||
int hashIterations = -1;
|
||||
int hashKeyLength = -1;
|
||||
String firstName;
|
||||
String lastname;
|
||||
UserState userState;
|
||||
|
@ -137,12 +140,46 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
if (qName.equals(XmlConstants.XML_USER)) {
|
||||
this.userId = attributes.getValue(XmlConstants.XML_ATTR_USER_ID);
|
||||
this.username = attributes.getValue(XmlConstants.XML_ATTR_USERNAME);
|
||||
String passwordS = attributes.getValue(XmlConstants.XML_ATTR_PASSWORD);
|
||||
if (!StringHelper.isEmpty(passwordS))
|
||||
this.password = StringHelper.fromHexString(passwordS);
|
||||
String saltS = attributes.getValue(XmlConstants.XML_ATTR_SALT);
|
||||
if (!StringHelper.isEmpty(saltS))
|
||||
this.salt = StringHelper.fromHexString(saltS);
|
||||
|
||||
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);
|
||||
} else {
|
||||
|
||||
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,30 +191,51 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
@Override
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
|
||||
if (qName.equals(XmlConstants.XML_FIRSTNAME)) {
|
||||
this.firstName = this.text.toString().trim();
|
||||
} 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)) {
|
||||
switch (qName) {
|
||||
case XmlConstants.XML_FIRSTNAME:
|
||||
|
||||
User user = new User(this.userId, this.username, this.password, this.salt, this.firstName,
|
||||
this.lastname, this.userState, this.userRoles, this.locale, this.parameters);
|
||||
this.firstName = this.text.toString().trim();
|
||||
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$
|
||||
|
||||
getUsers().add(user);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (!(qName.equals(XmlConstants.XML_ROLES) //
|
||||
|| qName.equals(XmlConstants.XML_PARAMETER) //
|
||||
|| qName.equals(XmlConstants.XML_PARAMETERS))) {
|
||||
throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,21 +249,27 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
|
||||
class PropertyParser extends ElementParserAdapter {
|
||||
|
||||
// <Property name="organizationalUnit" value="Development" />
|
||||
// <Property name="organizationalUnit" value="Development" />
|
||||
|
||||
public Map<String, String> parameterMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||
throws SAXException {
|
||||
if (qName.equals(XmlConstants.XML_PROPERTY)) {
|
||||
|
||||
switch (qName) {
|
||||
case XmlConstants.XML_PROPERTY:
|
||||
|
||||
String key = attributes.getValue(XmlConstants.XML_ATTR_NAME);
|
||||
String value = attributes.getValue(XmlConstants.XML_ATTR_VALUE);
|
||||
this.parameterMap.put(key, value);
|
||||
} else if (qName.equals(XmlConstants.XML_PROPERTIES)) {
|
||||
// NO-OP
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (!qName.equals(XmlConstants.XML_PROPERTIES)) {
|
||||
throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
|
|||
private static final String ROLE_PRIVILEGE_ADMIN = "PrivilegeAdmin";
|
||||
private static final String PRIVILEGE_USER_ACCESS = "UserAccessPrivilege";
|
||||
private static final String ADMIN = "admin";
|
||||
private static final String ADMIN2 = "admin2";
|
||||
private static final char[] PASS_ADMIN = "admin".toCharArray();
|
||||
private static final String BOB = "bob";
|
||||
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
|
||||
public void testFailAuthenticationNOk() throws Exception {
|
||||
this.exception.expect(AccessDeniedException.class);
|
||||
|
@ -328,7 +338,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
|
|||
UserRep selectorRep = new UserRep(null, null, null, null, null,
|
||||
new HashSet<>(Collections.singletonList("PrivilegeAdmin")), null, null);
|
||||
List<UserRep> users = this.privilegeHandler.queryUsers(certificate, selectorRep);
|
||||
assertEquals(1, users.size());
|
||||
assertEquals(2, users.size());
|
||||
assertEquals(ADMIN, users.get(0).getUsername());
|
||||
|
||||
} finally {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -36,7 +36,6 @@ import li.strolch.privilege.xml.*;
|
|||
import li.strolch.utils.helper.FileHelper;
|
||||
import li.strolch.utils.helper.StringHelper;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -52,23 +51,19 @@ public class XmlTest {
|
|||
private static final String SRC_TEST = "src/test/resources/config/";
|
||||
private static final Logger logger = LoggerFactory.getLogger(XmlTest.class);
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* if something goes wrong
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void init() throws Exception {
|
||||
public static void init() {
|
||||
|
||||
cleanUp();
|
||||
|
||||
File tmpDir = new File("target/test");
|
||||
if (tmpDir.exists())
|
||||
FileHelper.deleteFile(tmpDir, false);
|
||||
tmpDir.mkdirs();
|
||||
if (!tmpDir.mkdirs())
|
||||
throw new IllegalStateException("Could not create temp dir " + tmpDir.getAbsolutePath());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() throws Exception {
|
||||
public static void cleanUp() {
|
||||
|
||||
File tmpDir = new File("target/test");
|
||||
if (!tmpDir.exists())
|
||||
|
@ -161,7 +156,7 @@ public class XmlTest {
|
|||
List<User> users = xmlHandler.getUsers();
|
||||
assertNotNull(users);
|
||||
|
||||
assertEquals(3, users.size());
|
||||
assertEquals(4, users.size());
|
||||
|
||||
//
|
||||
// users
|
||||
|
@ -319,15 +314,15 @@ public class XmlTest {
|
|||
propertyMap.put("prop1", "value1");
|
||||
userRoles = new HashSet<>();
|
||||
userRoles.add("role1");
|
||||
User user1 = new User("1", "user1", "blabla".getBytes(), "blabla".getBytes(), "Bob", "White",
|
||||
UserState.DISABLED, userRoles, Locale.ENGLISH, propertyMap);
|
||||
User user1 = new User("1", "user1", "blabla".getBytes(), "blabla".getBytes(), "PBKDF2WithHmacSHA512", 10000,
|
||||
256, "Bob", "White", UserState.DISABLED, userRoles, Locale.ENGLISH, propertyMap);
|
||||
users.add(user1);
|
||||
|
||||
propertyMap = new HashMap<>();
|
||||
propertyMap.put("prop2", "value2");
|
||||
userRoles = new HashSet<>();
|
||||
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);
|
||||
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());
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
return new User(map.get("userId"), map.get("username"), null, null, map.get("firstName"), map.get("lastName"),
|
||||
UserState.ENABLED, roles, Locale.ENGLISH, properties);
|
||||
return new User(map.get("userId"), map.get("username"), null, null, null, -1, -1, map.get("firstName"),
|
||||
map.get("lastName"), UserState.ENABLED, roles, Locale.ENGLISH, properties);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,54 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Users>
|
||||
|
||||
<User userId="1" username="admin" password="cb69962946617da006a2f95776d78b49e5ec7941d2bdb2d25cdb05f957f64344" salt="61646d696e">
|
||||
<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="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="2" username="system_admin">
|
||||
<Firstname>System User</Firstname>
|
||||
<Lastname>Administrator</Lastname>
|
||||
<State>SYSTEM</State>
|
||||
<Locale>en_GB</Locale>
|
||||
<Roles>
|
||||
<Role>system_admin_privileges</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
<User userId="1" username="admin2" password="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918">
|
||||
<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="3" username="system_admin2">
|
||||
<Firstname>System User</Firstname>
|
||||
<Lastname>Administrator</Lastname>
|
||||
<State>SYSTEM</State>
|
||||
<Locale>en_GB</Locale>
|
||||
<Roles>
|
||||
<Role>system_admin_privileges</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
<User userId="2" username="system_admin">
|
||||
<Firstname>System User</Firstname>
|
||||
<Lastname>Administrator</Lastname>
|
||||
<State>SYSTEM</State>
|
||||
<Locale>en_GB</Locale>
|
||||
<Roles>
|
||||
<Role>system_admin_privileges</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
|
||||
<User userId="3" username="system_admin2">
|
||||
<Firstname>System User</Firstname>
|
||||
<Lastname>Administrator</Lastname>
|
||||
<State>SYSTEM</State>
|
||||
<Locale>en_GB</Locale>
|
||||
<Roles>
|
||||
<Role>system_admin_privileges</Role>
|
||||
</Roles>
|
||||
</User>
|
||||
|
||||
</Users>
|
Loading…
Reference in New Issue