Reformat code using spring-javaformat

Run `./gradlew format` to reformat all java files.

Issue gh-8945
This commit is contained in:
Phillip Webb 2020-08-10 16:39:17 -05:00 committed by Rob Winch
parent 81d9c6cac5
commit b7fc18262d
2487 changed files with 41506 additions and 46548 deletions

View File

@ -92,10 +92,10 @@ import org.springframework.util.StringUtils;
* <p> * <p>
* All comparisons and prefixes are case sensitive. * All comparisons and prefixes are case sensitive.
* *
*
* @author Ben Alex * @author Ben Alex
*/ */
public class AclEntryVoter extends AbstractAclVoter { public class AclEntryVoter extends AbstractAclVoter {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
@ -105,23 +105,26 @@ public class AclEntryVoter extends AbstractAclVoter {
// ================================================================================================ // ================================================================================================
private AclService aclService; private AclService aclService;
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
private String internalMethod; private String internalMethod;
private String processConfigAttribute; private String processConfigAttribute;
private List<Permission> requirePermission; private List<Permission> requirePermission;
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
public AclEntryVoter(AclService aclService, String processConfigAttribute, public AclEntryVoter(AclService aclService, String processConfigAttribute, Permission[] requirePermission) {
Permission[] requirePermission) {
Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory"); Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory");
Assert.notNull(aclService, "An AclService is mandatory"); Assert.notNull(aclService, "An AclService is mandatory");
if ((requirePermission == null) || (requirePermission.length == 0)) { if ((requirePermission == null) || (requirePermission.length == 0)) {
throw new IllegalArgumentException( throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
"One or more requirePermission entries is mandatory");
} }
this.aclService = aclService; this.aclService = aclService;
@ -138,7 +141,6 @@ public class AclEntryVoter extends AbstractAclVoter {
* evaluation. This is useful if a domain object contains a parent that an ACL * evaluation. This is useful if a domain object contains a parent that an ACL
* evaluation should be targeted for, instead of the child domain object (which * evaluation should be targeted for, instead of the child domain object (which
* perhaps is being created and as such does not yet have any ACL permissions) * perhaps is being created and as such does not yet have any ACL permissions)
*
* @return <code>null</code> to use the domain object, or the name of a method (that * @return <code>null</code> to use the domain object, or the name of a method (that
* requires no arguments) that should be invoked to obtain an <code>Object</code> * requires no arguments) that should be invoked to obtain an <code>Object</code>
* which will be the domain object used for ACL evaluation * which will be the domain object used for ACL evaluation
@ -155,10 +157,8 @@ public class AclEntryVoter extends AbstractAclVoter {
return processConfigAttribute; return processConfigAttribute;
} }
public void setObjectIdentityRetrievalStrategy( public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required");
Assert.notNull(objectIdentityRetrievalStrategy,
"ObjectIdentityRetrievalStrategy required");
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
} }
@ -168,12 +168,10 @@ public class AclEntryVoter extends AbstractAclVoter {
} }
public boolean supports(ConfigAttribute attribute) { public boolean supports(ConfigAttribute attribute) {
return (attribute.getAttribute() != null) return (attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute());
&& attribute.getAttribute().equals(getProcessConfigAttribute());
} }
public int vote(Authentication authentication, MethodInvocation object, public int vote(Authentication authentication, MethodInvocation object, Collection<ConfigAttribute> attributes) {
Collection<ConfigAttribute> attributes) {
for (ConfigAttribute attr : attributes) { for (ConfigAttribute attr : attributes) {
@ -201,30 +199,25 @@ public class AclEntryVoter extends AbstractAclVoter {
domainObject = method.invoke(domainObject); domainObject = method.invoke(domainObject);
} }
catch (NoSuchMethodException nsme) { catch (NoSuchMethodException nsme) {
throw new AuthorizationServiceException("Object of class '" throw new AuthorizationServiceException("Object of class '" + domainObject.getClass()
+ domainObject.getClass() + "' does not provide the requested internalMethod: " + internalMethod);
+ "' does not provide the requested internalMethod: "
+ internalMethod);
} }
catch (IllegalAccessException iae) { catch (IllegalAccessException iae) {
logger.debug("IllegalAccessException", iae); logger.debug("IllegalAccessException", iae);
throw new AuthorizationServiceException( throw new AuthorizationServiceException(
"Problem invoking internalMethod: " + internalMethod "Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject);
+ " for object: " + domainObject);
} }
catch (InvocationTargetException ite) { catch (InvocationTargetException ite) {
logger.debug("InvocationTargetException", ite); logger.debug("InvocationTargetException", ite);
throw new AuthorizationServiceException( throw new AuthorizationServiceException(
"Problem invoking internalMethod: " + internalMethod "Problem invoking internalMethod: " + internalMethod + " for object: " + domainObject);
+ " for object: " + domainObject);
} }
} }
// Obtain the OID applicable to the domain object // Obtain the OID applicable to the domain object
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
.getObjectIdentity(domainObject);
// Obtain the SIDs applicable to the principal // Obtain the SIDs applicable to the principal
List<Sid> sids = sidRetrievalStrategy.getSids(authentication); List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
@ -253,7 +246,8 @@ public class AclEntryVoter extends AbstractAclVoter {
} }
else { else {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Voting to deny access - ACLs returned, but insufficient permissions for this principal"); logger.debug(
"Voting to deny access - ACLs returned, but insufficient permissions for this principal");
} }
return ACCESS_DENIED; return ACCESS_DENIED;
@ -271,4 +265,5 @@ public class AclEntryVoter extends AbstractAclVoter {
// No configuration attribute matched, so abstain // No configuration attribute matched, so abstain
return ACCESS_ABSTAIN; return ACCESS_ABSTAIN;
} }
} }

View File

@ -38,9 +38,13 @@ import org.springframework.security.core.Authentication;
* @since 3.1 * @since 3.1
*/ */
public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer { public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer {
private final Log logger = LogFactory.getLog(getClass()); private final Log logger = LogFactory.getLog(getClass());
private final AclService aclService; private final AclService aclService;
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
private ObjectIdentityRetrievalStrategy oidRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); private ObjectIdentityRetrievalStrategy oidRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
public AclPermissionCacheOptimizer(AclService aclService) { public AclPermissionCacheOptimizer(AclService aclService) {
@ -71,12 +75,12 @@ public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer {
aclService.readAclsById(oidsToCache, sids); aclService.readAclsById(oidsToCache, sids);
} }
public void setObjectIdentityRetrievalStrategy( public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
this.oidRetrievalStrategy = objectIdentityRetrievalStrategy; this.oidRetrievalStrategy = objectIdentityRetrievalStrategy;
} }
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) { public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
this.sidRetrievalStrategy = sidRetrievalStrategy; this.sidRetrievalStrategy = sidRetrievalStrategy;
} }
} }

View File

@ -51,9 +51,13 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
private final Log logger = LogFactory.getLog(getClass()); private final Log logger = LogFactory.getLog(getClass());
private final AclService aclService; private final AclService aclService;
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
private ObjectIdentityGenerator objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl(); private ObjectIdentityGenerator objectIdentityGenerator = new ObjectIdentityRetrievalStrategyImpl();
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
private PermissionFactory permissionFactory = new DefaultPermissionFactory(); private PermissionFactory permissionFactory = new DefaultPermissionFactory();
public AclPermissionEvaluator(AclService aclService) { public AclPermissionEvaluator(AclService aclService) {
@ -65,28 +69,24 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
* the ACL configuration. If the domain object is null, returns false (this can always * the ACL configuration. If the domain object is null, returns false (this can always
* be overridden using a null check in the expression itself). * be overridden using a null check in the expression itself).
*/ */
public boolean hasPermission(Authentication authentication, Object domainObject, public boolean hasPermission(Authentication authentication, Object domainObject, Object permission) {
Object permission) {
if (domainObject == null) { if (domainObject == null) {
return false; return false;
} }
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
.getObjectIdentity(domainObject);
return checkPermission(authentication, objectIdentity, permission); return checkPermission(authentication, objectIdentity, permission);
} }
public boolean hasPermission(Authentication authentication, Serializable targetId, public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
String targetType, Object permission) {
ObjectIdentity objectIdentity = objectIdentityGenerator.createObjectIdentity(
targetId, targetType);
return checkPermission(authentication, objectIdentity, permission);
}
private boolean checkPermission(Authentication authentication, ObjectIdentity oid,
Object permission) { Object permission) {
ObjectIdentity objectIdentity = objectIdentityGenerator.createObjectIdentity(targetId, targetType);
return checkPermission(authentication, objectIdentity, permission);
}
private boolean checkPermission(Authentication authentication, ObjectIdentity oid, Object permission) {
// Obtain the SIDs applicable to the principal // Obtain the SIDs applicable to the principal
List<Sid> sids = sidRetrievalStrategy.getSids(authentication); List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
List<Permission> requiredPermission = resolvePermission(permission); List<Permission> requiredPermission = resolvePermission(permission);
@ -94,8 +94,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
final boolean debug = logger.isDebugEnabled(); final boolean debug = logger.isDebugEnabled();
if (debug) { if (debug) {
logger.debug("Checking permission '" + permission + "' for object '" + oid logger.debug("Checking permission '" + permission + "' for object '" + oid + "'");
+ "'");
} }
try { try {
@ -157,8 +156,7 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
throw new IllegalArgumentException("Unsupported permission: " + permission); throw new IllegalArgumentException("Unsupported permission: " + permission);
} }
public void setObjectIdentityRetrievalStrategy( public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
} }
@ -173,4 +171,5 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
public void setPermissionFactory(PermissionFactory permissionFactory) { public void setPermissionFactory(PermissionFactory permissionFactory) {
this.permissionFactory = permissionFactory; this.permissionFactory = permissionFactory;
} }
} }

View File

@ -40,14 +40,20 @@ import org.springframework.util.Assert;
* @author Ben Alex * @author Ben Alex
*/ */
public abstract class AbstractAclProvider implements AfterInvocationProvider { public abstract class AbstractAclProvider implements AfterInvocationProvider {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
protected final AclService aclService; protected final AclService aclService;
protected Class<?> processDomainObjectClass = Object.class; protected Class<?> processDomainObjectClass = Object.class;
protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl(); protected ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); protected SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
protected String processConfigAttribute; protected String processConfigAttribute;
protected final List<Permission> requirePermission; protected final List<Permission> requirePermission;
// ~ Constructors // ~ Constructors
@ -59,8 +65,7 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
Assert.notNull(aclService, "An AclService is mandatory"); Assert.notNull(aclService, "An AclService is mandatory");
if (requirePermission == null || requirePermission.isEmpty()) { if (requirePermission == null || requirePermission.isEmpty()) {
throw new IllegalArgumentException( throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
"One or more requirePermission entries is mandatory");
} }
this.aclService = aclService; this.aclService = aclService;
@ -77,8 +82,7 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
protected boolean hasPermission(Authentication authentication, Object domainObject) { protected boolean hasPermission(Authentication authentication, Object domainObject) {
// Obtain the OID applicable to the domain object // Obtain the OID applicable to the domain object
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
.getObjectIdentity(domainObject);
// Obtain the SIDs applicable to the principal // Obtain the SIDs applicable to the principal
List<Sid> sids = sidRetrievalStrategy.getSids(authentication); List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
@ -94,10 +98,8 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
} }
} }
public void setObjectIdentityRetrievalStrategy( public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) { Assert.notNull(objectIdentityRetrievalStrategy, "ObjectIdentityRetrievalStrategy required");
Assert.notNull(objectIdentityRetrievalStrategy,
"ObjectIdentityRetrievalStrategy required");
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy; this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
} }
@ -107,8 +109,7 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
} }
public void setProcessDomainObjectClass(Class<?> processDomainObjectClass) { public void setProcessDomainObjectClass(Class<?> processDomainObjectClass) {
Assert.notNull(processDomainObjectClass, Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null");
"processDomainObjectClass cannot be set to null");
this.processDomainObjectClass = processDomainObjectClass; this.processDomainObjectClass = processDomainObjectClass;
} }
@ -124,12 +125,11 @@ public abstract class AbstractAclProvider implements AfterInvocationProvider {
/** /**
* This implementation supports any type of class, because it does not query the * This implementation supports any type of class, because it does not query the
* presented secure object. * presented secure object.
*
* @param clazz the secure object * @param clazz the secure object
*
* @return always <code>true</code> * @return always <code>true</code>
*/ */
public boolean supports(Class<?> clazz) { public boolean supports(Class<?> clazz) {
return true; return true;
} }
} }

View File

@ -60,13 +60,12 @@ import org.springframework.security.core.Authentication;
* @author Ben Alex * @author Ben Alex
* @author Paulo Neves * @author Paulo Neves
*/ */
public class AclEntryAfterInvocationCollectionFilteringProvider extends public class AclEntryAfterInvocationCollectionFilteringProvider extends AbstractAclProvider {
AbstractAclProvider {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
protected static final Log logger = LogFactory protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class);
.getLog(AclEntryAfterInvocationCollectionFilteringProvider.class);
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
@ -80,9 +79,8 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends
// ======================================================================================================== // ========================================================================================================
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Object decide(Authentication authentication, Object object, public Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> config,
Collection<ConfigAttribute> config, Object returnedObject) Object returnedObject) throws AccessDeniedException {
throws AccessDeniedException {
if (returnedObject == null) { if (returnedObject == null) {
logger.debug("Return object is null, skipping"); logger.debug("Return object is null, skipping");
@ -105,19 +103,15 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends
filterer = new ArrayFilterer((Object[]) returnedObject); filterer = new ArrayFilterer((Object[]) returnedObject);
} }
else { else {
throw new AuthorizationServiceException( throw new AuthorizationServiceException("A Collection or an array (or null) was required as the "
"A Collection or an array (or null) was required as the " + "returnedObject, but the returnedObject was: " + returnedObject);
+ "returnedObject, but the returnedObject was: "
+ returnedObject);
} }
// Locate unauthorised Collection elements // Locate unauthorised Collection elements
for (Object domainObject : filterer) { for (Object domainObject : filterer) {
// Ignore nulls or entries which aren't instances of the configured domain // Ignore nulls or entries which aren't instances of the configured domain
// object class // object class
if (domainObject == null if (domainObject == null || !getProcessDomainObjectClass().isAssignableFrom(domainObject.getClass())) {
|| !getProcessDomainObjectClass().isAssignableFrom(
domainObject.getClass())) {
continue; continue;
} }
@ -125,8 +119,7 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends
filterer.remove(domainObject); filterer.remove(domainObject);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Principal is NOT authorised for element: " logger.debug("Principal is NOT authorised for element: " + domainObject);
+ domainObject);
} }
} }
} }
@ -136,4 +129,5 @@ public class AclEntryAfterInvocationCollectionFilteringProvider extends
return returnedObject; return returnedObject;
} }
} }

View File

@ -58,13 +58,12 @@ import org.springframework.security.core.SpringSecurityMessageSource;
* <p> * <p>
* All comparisons and prefixes are case sensitive. * All comparisons and prefixes are case sensitive.
*/ */
public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements public class AclEntryAfterInvocationProvider extends AbstractAclProvider implements MessageSourceAware {
MessageSourceAware {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
protected static final Log logger = LogFactory protected static final Log logger = LogFactory.getLog(AclEntryAfterInvocationProvider.class);
.getLog(AclEntryAfterInvocationProvider.class);
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
@ -74,22 +73,20 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
public AclEntryAfterInvocationProvider(AclService aclService, public AclEntryAfterInvocationProvider(AclService aclService, List<Permission> requirePermission) {
List<Permission> requirePermission) {
this(aclService, "AFTER_ACL_READ", requirePermission); this(aclService, "AFTER_ACL_READ", requirePermission);
} }
public AclEntryAfterInvocationProvider(AclService aclService, public AclEntryAfterInvocationProvider(AclService aclService, String processConfigAttribute,
String processConfigAttribute, List<Permission> requirePermission) { List<Permission> requirePermission) {
super(aclService, processConfigAttribute, requirePermission); super(aclService, processConfigAttribute, requirePermission);
} }
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
public Object decide(Authentication authentication, Object object, public Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> config,
Collection<ConfigAttribute> config, Object returnedObject) Object returnedObject) throws AccessDeniedException {
throws AccessDeniedException {
if (returnedObject == null) { if (returnedObject == null) {
// AclManager interface contract prohibits nulls // AclManager interface contract prohibits nulls
@ -117,9 +114,8 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
logger.debug("Denying access"); logger.debug("Denying access");
throw new AccessDeniedException(messages.getMessage( throw new AccessDeniedException(messages.getMessage("AclEntryAfterInvocationProvider.noPermission",
"AclEntryAfterInvocationProvider.noPermission", new Object[] { new Object[] { authentication.getName(), returnedObject },
authentication.getName(), returnedObject },
"Authentication {0} has NO permissions to the domain object {1}")); "Authentication {0} has NO permissions to the domain object {1}"));
} }
@ -129,4 +125,5 @@ public class AclEntryAfterInvocationProvider extends AbstractAclProvider impleme
public void setMessageSource(MessageSource messageSource) { public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource); this.messages = new MessageSourceAccessor(messageSource);
} }
} }

View File

@ -32,6 +32,7 @@ import org.apache.commons.logging.LogFactory;
* @author Paulo Neves * @author Paulo Neves
*/ */
class ArrayFilterer<T> implements Filterer<T> { class ArrayFilterer<T> implements Filterer<T> {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
@ -41,6 +42,7 @@ class ArrayFilterer<T> implements Filterer<T> {
// ================================================================================================ // ================================================================================================
private final Set<T> removeList; private final Set<T> removeList;
private final T[] list; private final T[] list;
// ~ Constructors // ~ Constructors
@ -67,8 +69,7 @@ class ArrayFilterer<T> implements Filterer<T> {
// Recreate an array of same type and filter the removed objects. // Recreate an array of same type and filter the removed objects.
int originalSize = list.length; int originalSize = list.length;
int sizeOfResultingList = originalSize - removeList.size(); int sizeOfResultingList = originalSize - removeList.size();
T[] filtered = (T[]) Array.newInstance(list.getClass().getComponentType(), T[] filtered = (T[]) Array.newInstance(list.getClass().getComponentType(), sizeOfResultingList);
sizeOfResultingList);
for (int i = 0, j = 0; i < list.length; i++) { for (int i = 0, j = 0; i < list.length; i++) {
T object = list[i]; T object = list[i];
@ -80,8 +81,8 @@ class ArrayFilterer<T> implements Filterer<T> {
} }
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Original array contained " + originalSize logger.debug("Original array contained " + originalSize + " elements; now contains " + sizeOfResultingList
+ " elements; now contains " + sizeOfResultingList + " elements"); + " elements");
} }
return filtered; return filtered;
@ -119,4 +120,5 @@ class ArrayFilterer<T> implements Filterer<T> {
public void remove(T object) { public void remove(T object) {
removeList.add(object); removeList.add(object);
} }
} }

View File

@ -31,6 +31,7 @@ import java.util.Set;
* @author Paulo Neves * @author Paulo Neves
*/ */
class CollectionFilterer<T> implements Filterer<T> { class CollectionFilterer<T> implements Filterer<T> {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
@ -77,8 +78,8 @@ class CollectionFilterer<T> implements Filterer<T> {
} }
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Original collection contained " + originalSize logger.debug("Original collection contained " + originalSize + " elements; now contains "
+ " elements; now contains " + collection.size() + " elements"); + collection.size() + " elements");
} }
return collection; return collection;
@ -99,4 +100,5 @@ class CollectionFilterer<T> implements Filterer<T> {
public void remove(T object) { public void remove(T object) {
removeList.add(object); removeList.add(object);
} }
} }

View File

@ -25,27 +25,26 @@ import java.util.Iterator;
* @author Paulo Neves * @author Paulo Neves
*/ */
interface Filterer<T> extends Iterable<T> { interface Filterer<T> extends Iterable<T> {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
/** /**
* Gets the filtered collection or array. * Gets the filtered collection or array.
*
* @return the filtered collection or array * @return the filtered collection or array
*/ */
Object getFilteredObject(); Object getFilteredObject();
/** /**
* Returns an iterator over the filtered collection or array. * Returns an iterator over the filtered collection or array.
*
* @return an Iterator * @return an Iterator
*/ */
Iterator<T> iterator(); Iterator<T> iterator();
/** /**
* Removes the given object from the resulting list. * Removes the given object from the resulting list.
*
* @param object the object to be removed * @param object the object to be removed
*/ */
void remove(T object); void remove(T object);
} }

View File

@ -14,8 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
/** /**
* After-invocation providers for collection and array filtering. Consider using a {@code PostFilter} annotation in * After-invocation providers for collection and array filtering. Consider using a
* preference. * {@code PostFilter} annotation in preference.
*/ */
package org.springframework.security.acls.afterinvocation; package org.springframework.security.acls.afterinvocation;

View File

@ -29,6 +29,7 @@ public abstract class AbstractPermission implements Permission {
// ================================================================================================ // ================================================================================================
protected final char code; protected final char code;
protected int mask; protected int mask;
// ~ Constructors // ~ Constructors
@ -36,7 +37,6 @@ public abstract class AbstractPermission implements Permission {
/** /**
* Sets the permission mask and uses the '*' character to represent active bits when * Sets the permission mask and uses the '*' character to represent active bits when
* represented as a bit pattern string. * represented as a bit pattern string.
*
* @param mask the integer bit mask for the permission * @param mask the integer bit mask for the permission
*/ */
protected AbstractPermission(int mask) { protected AbstractPermission(int mask) {
@ -46,7 +46,6 @@ public abstract class AbstractPermission implements Permission {
/** /**
* Sets the permission mask and uses the specified character for active bits. * Sets the permission mask and uses the specified character for active bits.
*
* @param mask the integer bit mask for the permission * @param mask the integer bit mask for the permission
* @param code the character to print for each active bit in the mask (see * @param code the character to print for each active bit in the mask (see
* {@link Permission#getPattern()}) * {@link Permission#getPattern()})
@ -88,4 +87,5 @@ public abstract class AbstractPermission implements Permission {
public final int hashCode() { public final int hashCode() {
return this.mask; return this.mask;
} }
} }

View File

@ -30,25 +30,30 @@ import java.io.Serializable;
* *
* @author Ben Alex * @author Ben Alex
*/ */
public class AccessControlEntryImpl implements AccessControlEntry, public class AccessControlEntryImpl implements AccessControlEntry, AuditableAccessControlEntry {
AuditableAccessControlEntry {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private final Acl acl; private final Acl acl;
private Permission permission; private Permission permission;
private final Serializable id; private final Serializable id;
private final Sid sid; private final Sid sid;
private boolean auditFailure = false; private boolean auditFailure = false;
private boolean auditSuccess = false; private boolean auditSuccess = false;
private final boolean granting; private final boolean granting;
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, public AccessControlEntryImpl(Serializable id, Acl acl, Sid sid, Permission permission, boolean granting,
Permission permission, boolean granting, boolean auditSuccess, boolean auditSuccess, boolean auditFailure) {
boolean auditFailure) {
Assert.notNull(acl, "Acl required"); Assert.notNull(acl, "Acl required");
Assert.notNull(sid, "Sid required"); Assert.notNull(sid, "Sid required");
Assert.notNull(permission, "Permission required"); Assert.notNull(permission, "Permission required");
@ -93,8 +98,7 @@ public class AccessControlEntryImpl implements AccessControlEntry,
} }
else { else {
// Both this.acl.objectIdentity and rhs.acl.objectIdentity are non-null // Both this.acl.objectIdentity and rhs.acl.objectIdentity are non-null
if (!this.acl.getObjectIdentity() if (!this.acl.getObjectIdentity().equals(rhs.getAcl().getObjectIdentity())) {
.equals(rhs.getAcl().getObjectIdentity())) {
return false; return false;
} }
} }
@ -118,10 +122,8 @@ public class AccessControlEntryImpl implements AccessControlEntry,
} }
} }
if ((this.auditFailure != rhs.isAuditFailure()) if ((this.auditFailure != rhs.isAuditFailure()) || (this.auditSuccess != rhs.isAuditSuccess())
|| (this.auditSuccess != rhs.isAuditSuccess()) || (this.granting != rhs.isGranting()) || !this.permission.equals(rhs.getPermission())
|| (this.granting != rhs.isGranting())
|| !this.permission.equals(rhs.getPermission())
|| !this.sid.equals(rhs.getSid())) { || !this.sid.equals(rhs.getSid())) {
return false; return false;
} }
@ -202,4 +204,5 @@ public class AccessControlEntryImpl implements AccessControlEntry,
return sb.toString(); return sb.toString();
} }
} }

View File

@ -25,15 +25,19 @@ import org.springframework.security.acls.model.Acl;
* @author Ben Alex * @author Ben Alex
*/ */
public interface AclAuthorizationStrategy { public interface AclAuthorizationStrategy {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
int CHANGE_OWNERSHIP = 0; int CHANGE_OWNERSHIP = 0;
int CHANGE_AUDITING = 1; int CHANGE_AUDITING = 1;
int CHANGE_GENERAL = 2; int CHANGE_GENERAL = 2;
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
void securityCheck(Acl acl, int changeType); void securityCheck(Acl acl, int changeType);
} }

View File

@ -45,12 +45,16 @@ import java.util.Set;
* @author Ben Alex * @author Ben Alex
*/ */
public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy { public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private final GrantedAuthority gaGeneralChanges; private final GrantedAuthority gaGeneralChanges;
private final GrantedAuthority gaModifyAuditing; private final GrantedAuthority gaModifyAuditing;
private final GrantedAuthority gaTakeOwnership; private final GrantedAuthority gaTakeOwnership;
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl(); private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
// ~ Constructors // ~ Constructors
@ -59,7 +63,6 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
/** /**
* Constructor. The only mandatory parameter relates to the system-wide * Constructor. The only mandatory parameter relates to the system-wide
* {@link GrantedAuthority} instances that can be held to always permit ACL changes. * {@link GrantedAuthority} instances that can be held to always permit ACL changes.
*
* @param auths the <code>GrantedAuthority</code>s that have special permissions * @param auths the <code>GrantedAuthority</code>s that have special permissions
* (index 0 is the authority needed to change ownership, index 1 is the authority * (index 0 is the authority needed to change ownership, index 1 is the authority
* needed to modify auditing details, index 2 is the authority needed to change other * needed to modify auditing details, index 2 is the authority needed to change other
@ -86,14 +89,11 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
public void securityCheck(Acl acl, int changeType) { public void securityCheck(Acl acl, int changeType) {
if ((SecurityContextHolder.getContext() == null) if ((SecurityContextHolder.getContext() == null)
|| (SecurityContextHolder.getContext().getAuthentication() == null) || (SecurityContextHolder.getContext().getAuthentication() == null)
|| !SecurityContextHolder.getContext().getAuthentication() || !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
.isAuthenticated()) { throw new AccessDeniedException("Authenticated principal required to operate with ACLs");
throw new AccessDeniedException(
"Authenticated principal required to operate with ACLs");
} }
Authentication authentication = SecurityContextHolder.getContext() Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
.getAuthentication();
// Check if authorized by virtue of ACL ownership // Check if authorized by virtue of ACL ownership
Sid currentUser = createCurrentUser(authentication); Sid currentUser = createCurrentUser(authentication);
@ -138,7 +138,6 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
/** /**
* Creates a principal-like sid from the authentication information. * Creates a principal-like sid from the authentication information.
*
* @param authentication the authentication information that can provide principal and * @param authentication the authentication information that can provide principal and
* thus the sid's id will be dependant on the value inside * thus the sid's id will be dependant on the value inside
* @return a sid with the ID taken from the authentication information * @return a sid with the ID taken from the authentication information
@ -151,4 +150,5 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required"); Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required");
this.sidRetrievalStrategy = sidRetrievalStrategy; this.sidRetrievalStrategy = sidRetrievalStrategy;
} }
} }

View File

@ -70,9 +70,7 @@ public abstract class AclFormattingUtils {
* bit being denoted by character '*'. * bit being denoted by character '*'.
* <p> * <p>
* Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. * Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}.
*
* @param i the integer bit mask to print the active bits for * @param i the integer bit mask to print the active bits for
*
* @return a 32-character representation of the bit mask * @return a 32-character representation of the bit mask
*/ */
public static String printBinary(int i) { public static String printBinary(int i) {
@ -84,22 +82,17 @@ public abstract class AclFormattingUtils {
* bit being denoted by the passed character. * bit being denoted by the passed character.
* <p> * <p>
* Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}. * Inactive bits will be denoted by character {@link Permission#RESERVED_OFF}.
*
* @param mask the integer bit mask to print the active bits for * @param mask the integer bit mask to print the active bits for
* @param code the character to print when an active bit is detected * @param code the character to print when an active bit is detected
*
* @return a 32-character representation of the bit mask * @return a 32-character representation of the bit mask
*/ */
public static String printBinary(int mask, char code) { public static String printBinary(int mask, char code) {
Assert.doesNotContain(Character.toString(code), Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_ON),
Character.toString(Permission.RESERVED_ON),
() -> Permission.RESERVED_ON + " is a reserved character code"); () -> Permission.RESERVED_ON + " is a reserved character code");
Assert.doesNotContain(Character.toString(code), Assert.doesNotContain(Character.toString(code), Character.toString(Permission.RESERVED_OFF),
Character.toString(Permission.RESERVED_OFF),
() -> Permission.RESERVED_OFF + " is a reserved character code"); () -> Permission.RESERVED_OFF + " is a reserved character code");
return printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF) return printBinary(mask, Permission.RESERVED_ON, Permission.RESERVED_OFF).replace(Permission.RESERVED_ON, code);
.replace(Permission.RESERVED_ON, code);
} }
private static String printBinary(int i, char on, char off) { private static String printBinary(int i, char on, char off) {
@ -109,4 +102,5 @@ public abstract class AclFormattingUtils {
return temp2.replace('0', off).replace('1', on); return temp2.replace('0', off).replace('1', on);
} }
} }

View File

@ -38,18 +38,27 @@ import org.springframework.util.Assert;
* @author Ben Alex * @author Ben Alex
*/ */
public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl { public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private Acl parentAcl; private Acl parentAcl;
private transient AclAuthorizationStrategy aclAuthorizationStrategy; private transient AclAuthorizationStrategy aclAuthorizationStrategy;
private transient PermissionGrantingStrategy permissionGrantingStrategy; private transient PermissionGrantingStrategy permissionGrantingStrategy;
private final List<AccessControlEntry> aces = new ArrayList<>(); private final List<AccessControlEntry> aces = new ArrayList<>();
private ObjectIdentity objectIdentity; private ObjectIdentity objectIdentity;
private Serializable id; private Serializable id;
private Sid owner; // OwnershipAcl private Sid owner; // OwnershipAcl
private List<Sid> loadedSids = null; // includes all SIDs the WHERE clause covered, private List<Sid> loadedSids = null; // includes all SIDs the WHERE clause covered,
// even if there was no ACE for a SID // even if there was no ACE for a SID
private boolean entriesInheriting = true; private boolean entriesInheriting = true;
// ~ Constructors // ~ Constructors
@ -59,14 +68,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* Minimal constructor, which should be used * Minimal constructor, which should be used
* {@link org.springframework.security.acls.model.MutableAclService#createAcl(ObjectIdentity)} * {@link org.springframework.security.acls.model.MutableAclService#createAcl(ObjectIdentity)}
* . * .
*
* @param objectIdentity the object identity this ACL relates to (required) * @param objectIdentity the object identity this ACL relates to (required)
* @param id the primary key assigned to this ACL (required) * @param id the primary key assigned to this ACL (required)
* @param aclAuthorizationStrategy authorization strategy (required) * @param aclAuthorizationStrategy authorization strategy (required)
* @param auditLogger audit logger (required) * @param auditLogger audit logger (required)
*/ */
public AclImpl(ObjectIdentity objectIdentity, Serializable id, public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { AuditLogger auditLogger) {
Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(objectIdentity, "Object Identity required");
Assert.notNull(id, "Id required"); Assert.notNull(id, "Id required");
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
@ -74,14 +82,12 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
this.objectIdentity = objectIdentity; this.objectIdentity = objectIdentity;
this.id = id; this.id = id;
this.aclAuthorizationStrategy = aclAuthorizationStrategy; this.aclAuthorizationStrategy = aclAuthorizationStrategy;
this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy( this.permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger);
auditLogger);
} }
/** /**
* Full constructor, which should be used by persistence tools that do not provide * Full constructor, which should be used by persistence tools that do not provide
* field-level access features. * field-level access features.
*
* @param objectIdentity the object identity this ACL relates to * @param objectIdentity the object identity this ACL relates to
* @param id the primary key assigned to this ACL * @param id the primary key assigned to this ACL
* @param aclAuthorizationStrategy authorization strategy * @param aclAuthorizationStrategy authorization strategy
@ -93,10 +99,9 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
* @param entriesInheriting if ACEs from the parent should inherit into this ACL * @param entriesInheriting if ACEs from the parent should inherit into this ACL
* @param owner the owner (required) * @param owner the owner (required)
*/ */
public AclImpl(ObjectIdentity objectIdentity, Serializable id, public AclImpl(ObjectIdentity objectIdentity, Serializable id, AclAuthorizationStrategy aclAuthorizationStrategy,
AclAuthorizationStrategy aclAuthorizationStrategy, PermissionGrantingStrategy grantingStrategy, Acl parentAcl, List<Sid> loadedSids, boolean entriesInheriting,
PermissionGrantingStrategy grantingStrategy, Acl parentAcl, Sid owner) {
List<Sid> loadedSids, boolean entriesInheriting, Sid owner) {
Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(objectIdentity, "Object Identity required");
Assert.notNull(id, "Id required"); Assert.notNull(id, "Id required");
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
@ -125,8 +130,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
@Override @Override
public void deleteAce(int aceIndex) throws NotFoundException { public void deleteAce(int aceIndex) throws NotFoundException {
aclAuthorizationStrategy.securityCheck(this, aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL);
verifyAceIndexExists(aceIndex); verifyAceIndexExists(aceIndex);
synchronized (aces) { synchronized (aces) {
@ -139,30 +143,26 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
throw new NotFoundException("aceIndex must be greater than or equal to zero"); throw new NotFoundException("aceIndex must be greater than or equal to zero");
} }
if (aceIndex >= this.aces.size()) { if (aceIndex >= this.aces.size()) {
throw new NotFoundException( throw new NotFoundException("aceIndex must refer to an index of the AccessControlEntry list. "
"aceIndex must refer to an index of the AccessControlEntry list. " + "List size is " + aces.size() + ", index was " + aceIndex);
+ "List size is " + aces.size() + ", index was " + aceIndex);
} }
} }
@Override @Override
public void insertAce(int atIndexLocation, Permission permission, Sid sid, public void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting)
boolean granting) throws NotFoundException { throws NotFoundException {
aclAuthorizationStrategy.securityCheck(this, aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL);
Assert.notNull(permission, "Permission required"); Assert.notNull(permission, "Permission required");
Assert.notNull(sid, "Sid required"); Assert.notNull(sid, "Sid required");
if (atIndexLocation < 0) { if (atIndexLocation < 0) {
throw new NotFoundException( throw new NotFoundException("atIndexLocation must be greater than or equal to zero");
"atIndexLocation must be greater than or equal to zero");
} }
if (atIndexLocation > this.aces.size()) { if (atIndexLocation > this.aces.size()) {
throw new NotFoundException( throw new NotFoundException(
"atIndexLocation must be less than or equal to the size of the AccessControlEntry collection"); "atIndexLocation must be less than or equal to the size of the AccessControlEntry collection");
} }
AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid, AccessControlEntryImpl ace = new AccessControlEntryImpl(null, this, sid, permission, granting, false, false);
permission, granting, false, false);
synchronized (aces) { synchronized (aces) {
this.aces.add(atIndexLocation, ace); this.aces.add(atIndexLocation, ace);
@ -193,14 +193,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
/** /**
* Delegates to the {@link PermissionGrantingStrategy}. * Delegates to the {@link PermissionGrantingStrategy}.
*
* @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the * @throws UnloadedSidException if the passed SIDs are unknown to this ACL because the
* ACL was only loaded for a subset of SIDs * ACL was only loaded for a subset of SIDs
* @see DefaultPermissionGrantingStrategy * @see DefaultPermissionGrantingStrategy
*/ */
@Override @Override
public boolean isGranted(List<Permission> permission, List<Sid> sids, public boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
boolean administrativeMode) throws NotFoundException, UnloadedSidException { throws NotFoundException, UnloadedSidException {
Assert.notEmpty(permission, "Permissions required"); Assert.notEmpty(permission, "Permissions required");
Assert.notEmpty(sids, "SIDs required"); Assert.notEmpty(sids, "SIDs required");
@ -208,8 +207,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
throw new UnloadedSidException("ACL was not loaded for one or more SID"); throw new UnloadedSidException("ACL was not loaded for one or more SID");
} }
return permissionGrantingStrategy.isGranted(this, permission, sids, return permissionGrantingStrategy.isGranted(this, permission, sids, administrativeMode);
administrativeMode);
} }
@Override @Override
@ -243,15 +241,13 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
@Override @Override
public void setEntriesInheriting(boolean entriesInheriting) { public void setEntriesInheriting(boolean entriesInheriting) {
aclAuthorizationStrategy.securityCheck(this, aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL);
this.entriesInheriting = entriesInheriting; this.entriesInheriting = entriesInheriting;
} }
@Override @Override
public void setOwner(Sid newOwner) { public void setOwner(Sid newOwner) {
aclAuthorizationStrategy.securityCheck(this, aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
Assert.notNull(newOwner, "Owner required"); Assert.notNull(newOwner, "Owner required");
this.owner = newOwner; this.owner = newOwner;
} }
@ -263,10 +259,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
@Override @Override
public void setParent(Acl newParent) { public void setParent(Acl newParent) {
aclAuthorizationStrategy.securityCheck(this, aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL); Assert.isTrue(newParent == null || !newParent.equals(this), "Cannot be the parent of yourself");
Assert.isTrue(newParent == null || !newParent.equals(this),
"Cannot be the parent of yourself");
this.parentAcl = newParent; this.parentAcl = newParent;
} }
@ -277,8 +271,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
@Override @Override
public void updateAce(int aceIndex, Permission permission) throws NotFoundException { public void updateAce(int aceIndex, Permission permission) throws NotFoundException {
aclAuthorizationStrategy.securityCheck(this, aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL);
verifyAceIndexExists(aceIndex); verifyAceIndexExists(aceIndex);
synchronized (aces) { synchronized (aces) {
@ -289,8 +282,7 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
@Override @Override
public void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure) { public void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure) {
aclAuthorizationStrategy.securityCheck(this, aclAuthorizationStrategy.securityCheck(this, AclAuthorizationStrategy.CHANGE_AUDITING);
AclAuthorizationStrategy.CHANGE_AUDITING);
verifyAceIndexExists(aceIndex); verifyAceIndexExists(aceIndex);
synchronized (aces) { synchronized (aces) {
@ -306,26 +298,19 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
AclImpl rhs = (AclImpl) obj; AclImpl rhs = (AclImpl) obj;
if (this.aces.equals(rhs.aces)) { if (this.aces.equals(rhs.aces)) {
if ((this.parentAcl == null && rhs.parentAcl == null) if ((this.parentAcl == null && rhs.parentAcl == null)
|| (this.parentAcl != null && this.parentAcl || (this.parentAcl != null && this.parentAcl.equals(rhs.parentAcl))) {
.equals(rhs.parentAcl))) {
if ((this.objectIdentity == null && rhs.objectIdentity == null) if ((this.objectIdentity == null && rhs.objectIdentity == null)
|| (this.objectIdentity != null && this.objectIdentity || (this.objectIdentity != null && this.objectIdentity.equals(rhs.objectIdentity))) {
.equals(rhs.objectIdentity))) { if ((this.id == null && rhs.id == null) || (this.id != null && this.id.equals(rhs.id))) {
if ((this.id == null && rhs.id == null)
|| (this.id != null && this.id.equals(rhs.id))) {
if ((this.owner == null && rhs.owner == null) if ((this.owner == null && rhs.owner == null)
|| (this.owner != null && this.owner || (this.owner != null && this.owner.equals(rhs.owner))) {
.equals(rhs.owner))) {
if (this.entriesInheriting == rhs.entriesInheriting) { if (this.entriesInheriting == rhs.entriesInheriting) {
if ((this.loadedSids == null && rhs.loadedSids == null)) { if ((this.loadedSids == null && rhs.loadedSids == null)) {
return true; return true;
} }
if (this.loadedSids != null if (this.loadedSids != null && (this.loadedSids.size() == rhs.loadedSids.size())) {
&& (this.loadedSids.size() == rhs.loadedSids
.size())) {
for (int i = 0; i < this.loadedSids.size(); i++) { for (int i = 0; i < this.loadedSids.size(); i++) {
if (!this.loadedSids.get(i).equals( if (!this.loadedSids.get(i).equals(rhs.loadedSids.get(i))) {
rhs.loadedSids.get(i))) {
return false; return false;
} }
} }
@ -345,9 +330,8 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
public int hashCode() { public int hashCode() {
int result = this.parentAcl != null ? this.parentAcl.hashCode() : 0; int result = this.parentAcl != null ? this.parentAcl.hashCode() : 0;
result = 31 * result + this.aclAuthorizationStrategy.hashCode(); result = 31 * result + this.aclAuthorizationStrategy.hashCode();
result = 31 * result + (this.permissionGrantingStrategy != null ? result = 31 * result
this.permissionGrantingStrategy.hashCode() : + (this.permissionGrantingStrategy != null ? this.permissionGrantingStrategy.hashCode() : 0);
0);
result = 31 * result + (this.aces != null ? this.aces.hashCode() : 0); result = 31 * result + (this.aces != null ? this.aces.hashCode() : 0);
result = 31 * result + this.objectIdentity.hashCode(); result = 31 * result + this.objectIdentity.hashCode();
result = 31 * result + this.id.hashCode(); result = 31 * result + this.id.hashCode();
@ -382,12 +366,9 @@ public class AclImpl implements Acl, MutableAcl, AuditableAcl, OwnershipAcl {
} }
sb.append("inheriting: ").append(this.entriesInheriting).append("; "); sb.append("inheriting: ").append(this.entriesInheriting).append("; ");
sb.append("parent: ").append( sb.append("parent: ").append((this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity().toString());
(this.parentAcl == null) ? "Null" : this.parentAcl.getObjectIdentity()
.toString());
sb.append("; "); sb.append("; ");
sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy) sb.append("aclAuthorizationStrategy: ").append(this.aclAuthorizationStrategy).append("; ");
.append("; ");
sb.append("permissionGrantingStrategy: ").append(this.permissionGrantingStrategy); sb.append("permissionGrantingStrategy: ").append(this.permissionGrantingStrategy);
sb.append("]"); sb.append("]");

View File

@ -24,8 +24,10 @@ import org.springframework.security.acls.model.AccessControlEntry;
* *
*/ */
public interface AuditLogger { public interface AuditLogger {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
void logIfNeeded(boolean granted, AccessControlEntry ace); void logIfNeeded(boolean granted, AccessControlEntry ace);
} }

View File

@ -28,10 +28,15 @@ import org.springframework.security.acls.model.Permission;
* @author Ben Alex * @author Ben Alex
*/ */
public class BasePermission extends AbstractPermission { public class BasePermission extends AbstractPermission {
public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1 public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2 public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4 public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8 public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16 public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16
protected BasePermission(int mask) { protected BasePermission(int mask) {
@ -41,4 +46,5 @@ public class BasePermission extends AbstractPermission {
protected BasePermission(int mask, char code) { protected BasePermission(int mask, char code) {
super(mask, code); super(mask, code);
} }
} }

View File

@ -26,6 +26,7 @@ import org.springframework.util.Assert;
* @author Ben Alex * @author Ben Alex
*/ */
public class ConsoleAuditLogger implements AuditLogger { public class ConsoleAuditLogger implements AuditLogger {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
@ -43,4 +44,5 @@ public class ConsoleAuditLogger implements AuditLogger {
} }
} }
} }
} }

View File

@ -37,8 +37,7 @@ public class CumulativePermission extends AbstractPermission {
public CumulativePermission clear(Permission permission) { public CumulativePermission clear(Permission permission) {
this.mask &= ~permission.getMask(); this.mask &= ~permission.getMask();
this.pattern = AclFormattingUtils.demergePatterns(this.pattern, this.pattern = AclFormattingUtils.demergePatterns(this.pattern, permission.getPattern());
permission.getPattern());
return this; return this;
} }
@ -52,8 +51,7 @@ public class CumulativePermission extends AbstractPermission {
public CumulativePermission set(Permission permission) { public CumulativePermission set(Permission permission) {
this.mask |= permission.getMask(); this.mask |= permission.getMask();
this.pattern = AclFormattingUtils.mergePatterns(this.pattern, this.pattern = AclFormattingUtils.mergePatterns(this.pattern, permission.getPattern());
permission.getPattern());
return this; return this;
} }

View File

@ -38,7 +38,9 @@ import org.springframework.util.Assert;
* @since 2.0.3 * @since 2.0.3
*/ */
public class DefaultPermissionFactory implements PermissionFactory { public class DefaultPermissionFactory implements PermissionFactory {
private final Map<Integer, Permission> registeredPermissionsByInteger = new HashMap<>(); private final Map<Integer, Permission> registeredPermissionsByInteger = new HashMap<>();
private final Map<String, Permission> registeredPermissionsByName = new HashMap<>(); private final Map<String, Permission> registeredPermissionsByName = new HashMap<>();
/** /**
@ -57,7 +59,6 @@ public class DefaultPermissionFactory implements PermissionFactory {
/** /**
* Registers a map of named <tt>Permission</tt> instances. * Registers a map of named <tt>Permission</tt> instances.
*
* @param namedPermissions the map of <tt>Permission</tt>s, keyed by name. * @param namedPermissions the map of <tt>Permission</tt>s, keyed by name.
*/ */
public DefaultPermissionFactory(Map<String, ? extends Permission> namedPermissions) { public DefaultPermissionFactory(Map<String, ? extends Permission> namedPermissions) {
@ -71,7 +72,6 @@ public class DefaultPermissionFactory implements PermissionFactory {
* <p> * <p>
* These permissions will be registered under the name of the field. See * These permissions will be registered under the name of the field. See
* {@link BasePermission} for an example. * {@link BasePermission} for an example.
*
* @param clazz a {@link Permission} class with public static fields to register * @param clazz a {@link Permission} class with public static fields to register
*/ */
protected void registerPublicPermissions(Class<? extends Permission> clazz) { protected void registerPublicPermissions(Class<? extends Permission> clazz) {
@ -130,8 +130,8 @@ public class DefaultPermissionFactory implements PermissionFactory {
Permission p = registeredPermissionsByInteger.get(permissionToCheck); Permission p = registeredPermissionsByInteger.get(permissionToCheck);
if (p == null) { if (p == null) {
throw new IllegalStateException("Mask '" + permissionToCheck throw new IllegalStateException(
+ "' does not have a corresponding static Permission"); "Mask '" + permissionToCheck + "' does not have a corresponding static Permission");
} }
permission.set(p); permission.set(p);
} }

View File

@ -61,20 +61,17 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra
* decide how to handle the permission check. Similarly, if any of the SID arguments * decide how to handle the permission check. Similarly, if any of the SID arguments
* presented to the method were not loaded by the ACL, * presented to the method were not loaded by the ACL,
* <code>UnloadedSidException</code> will be thrown. * <code>UnloadedSidException</code> will be thrown.
*
* @param permission the exact permissions to scan for (order is important) * @param permission the exact permissions to scan for (order is important)
* @param sids the exact SIDs to scan for (order is important) * @param sids the exact SIDs to scan for (order is important)
* @param administrativeMode if <code>true</code> denotes the query is for * @param administrativeMode if <code>true</code> denotes the query is for
* administrative purposes and no auditing will be undertaken * administrative purposes and no auditing will be undertaken
*
* @return <code>true</code> if one of the permissions has been granted, * @return <code>true</code> if one of the permissions has been granted,
* <code>false</code> if one of the permissions has been specifically revoked * <code>false</code> if one of the permissions has been specifically revoked
*
* @throws NotFoundException if an exact ACE for one of the permission bit masks and * @throws NotFoundException if an exact ACE for one of the permission bit masks and
* SID combination could not be found * SID combination could not be found
*/ */
public boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids, public boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids, boolean administrativeMode)
boolean administrativeMode) throws NotFoundException { throws NotFoundException {
final List<AccessControlEntry> aces = acl.getEntries(); final List<AccessControlEntry> aces = acl.getEntries();
@ -87,8 +84,7 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra
for (AccessControlEntry ace : aces) { for (AccessControlEntry ace : aces) {
if (isGranted(ace, p) if (isGranted(ace, p) && ace.getSid().equals(sid)) {
&& ace.getSid().equals(sid)) {
// Found a matching ACE, so its authorization decision will // Found a matching ACE, so its authorization decision will
// prevail // prevail
if (ace.isGranting()) { if (ace.isGranting()) {
@ -137,24 +133,21 @@ public class DefaultPermissionGrantingStrategy implements PermissionGrantingStra
} }
else { else {
// We either have no parent, or we're the uppermost parent // We either have no parent, or we're the uppermost parent
throw new NotFoundException( throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs");
"Unable to locate a matching ACE for passed permissions and SIDs");
} }
} }
/** /**
* Compares an ACE Permission to the given Permission. * Compares an ACE Permission to the given Permission. By default, we compare the
* By default, we compare the Permission masks for exact match. * Permission masks for exact match. Subclasses of this strategy can override this
* Subclasses of this strategy can override this behavior and implement * behavior and implement more sophisticated comparisons, e.g. a bitwise comparison
* more sophisticated comparisons, e.g. a bitwise comparison for ACEs that grant access. * for ACEs that grant access. <pre>{@code
* <pre>{@code
* if (ace.isGranting() && p.getMask() != 0) { * if (ace.isGranting() && p.getMask() != 0) {
* return (ace.getPermission().getMask() & p.getMask()) != 0; * return (ace.getPermission().getMask() & p.getMask()) != 0;
* } else { * } else {
* return ace.getPermission().getMask() == p.getMask(); * return ace.getPermission().getMask() == p.getMask();
* } * }
* }</pre> * }</pre>
*
* @param ace the ACE from the Acl holding the mask. * @param ace the ACE from the Acl holding the mask.
* @param p the Permission we are checking against. * @param p the Permission we are checking against.
* @return true, if the respective masks are considered to be equal. * @return true, if the respective masks are considered to be equal.

View File

@ -38,18 +38,20 @@ import org.springframework.util.Assert;
* @author Ben Alex * @author Ben Alex
*/ */
public class EhCacheBasedAclCache implements AclCache { public class EhCacheBasedAclCache implements AclCache {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private final Ehcache cache; private final Ehcache cache;
private PermissionGrantingStrategy permissionGrantingStrategy; private PermissionGrantingStrategy permissionGrantingStrategy;
private AclAuthorizationStrategy aclAuthorizationStrategy; private AclAuthorizationStrategy aclAuthorizationStrategy;
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
public EhCacheBasedAclCache(Ehcache cache, public EhCacheBasedAclCache(Ehcache cache, PermissionGrantingStrategy permissionGrantingStrategy,
PermissionGrantingStrategy permissionGrantingStrategy,
AclAuthorizationStrategy aclAuthorizationStrategy) { AclAuthorizationStrategy aclAuthorizationStrategy) {
Assert.notNull(cache, "Cache required"); Assert.notNull(cache, "Cache required");
Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required"); Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required");
@ -144,10 +146,8 @@ public class EhCacheBasedAclCache implements AclCache {
private MutableAcl initializeTransientFields(MutableAcl value) { private MutableAcl initializeTransientFields(MutableAcl value) {
if (value instanceof AclImpl) { if (value instanceof AclImpl) {
FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy);
this.aclAuthorizationStrategy); FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy);
FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value,
this.permissionGrantingStrategy);
} }
if (value.getParentAcl() != null) { if (value.getParentAcl() != null) {
@ -159,4 +159,5 @@ public class EhCacheBasedAclCache implements AclCache {
public void clearCache() { public void clearCache() {
cache.removeAll(); cache.removeAll();
} }
} }

View File

@ -31,6 +31,7 @@ import org.springframework.util.Assert;
* @author Ben Alex * @author Ben Alex
*/ */
public class GrantedAuthoritySid implements Sid { public class GrantedAuthoritySid implements Sid {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
@ -46,8 +47,7 @@ public class GrantedAuthoritySid implements Sid {
public GrantedAuthoritySid(GrantedAuthority grantedAuthority) { public GrantedAuthoritySid(GrantedAuthority grantedAuthority) {
Assert.notNull(grantedAuthority, "GrantedAuthority required"); Assert.notNull(grantedAuthority, "GrantedAuthority required");
Assert.notNull( Assert.notNull(grantedAuthority.getAuthority(),
grantedAuthority.getAuthority(),
"This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()"); "This Sid is only compatible with GrantedAuthoritys that provide a non-null getAuthority()");
this.grantedAuthority = grantedAuthority.getAuthority(); this.grantedAuthority = grantedAuthority.getAuthority();
} }
@ -63,8 +63,7 @@ public class GrantedAuthoritySid implements Sid {
// Delegate to getGrantedAuthority() to perform actual comparison (both should be // Delegate to getGrantedAuthority() to perform actual comparison (both should be
// identical) // identical)
return ((GrantedAuthoritySid) object).getGrantedAuthority().equals( return ((GrantedAuthoritySid) object).getGrantedAuthority().equals(this.getGrantedAuthority());
this.getGrantedAuthority());
} }
@Override @Override
@ -80,4 +79,5 @@ public class GrantedAuthoritySid implements Sid {
public String toString() { public String toString() {
return "GrantedAuthoritySid[" + this.grantedAuthority + "]"; return "GrantedAuthoritySid[" + this.grantedAuthority + "]";
} }
} }

View File

@ -21,12 +21,12 @@ package org.springframework.security.acls.domain;
* @author Ben Alex * @author Ben Alex
*/ */
public class IdentityUnavailableException extends RuntimeException { public class IdentityUnavailableException extends RuntimeException {
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
/** /**
* Constructs an <code>IdentityUnavailableException</code> with the specified message. * Constructs an <code>IdentityUnavailableException</code> with the specified message.
*
* @param msg the detail message * @param msg the detail message
*/ */
public IdentityUnavailableException(String msg) { public IdentityUnavailableException(String msg) {
@ -36,11 +36,11 @@ public class IdentityUnavailableException extends RuntimeException {
/** /**
* Constructs an <code>IdentityUnavailableException</code> with the specified message * Constructs an <code>IdentityUnavailableException</code> with the specified message
* and root cause. * and root cause.
*
* @param msg the detail message * @param msg the detail message
* @param t root cause * @param t root cause
*/ */
public IdentityUnavailableException(String msg, Throwable t) { public IdentityUnavailableException(String msg, Throwable t) {
super(msg, t); super(msg, t);
} }
} }

View File

@ -31,10 +31,12 @@ import org.springframework.util.ClassUtils;
* @author Ben Alex * @author Ben Alex
*/ */
public class ObjectIdentityImpl implements ObjectIdentity { public class ObjectIdentityImpl implements ObjectIdentity {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private final String type; private final String type;
private Serializable identifier; private Serializable identifier;
// ~ Constructors // ~ Constructors
@ -66,9 +68,7 @@ public class ObjectIdentityImpl implements ObjectIdentity {
* <p> * <p>
* The class name of the object passed will be considered the {@link #type}, so if * The class name of the object passed will be considered the {@link #type}, so if
* more control is required, a different constructor should be used. * more control is required, a different constructor should be used.
*
* @param object the domain object instance to create an identity for. * @param object the domain object instance to create an identity for.
*
* @throws IdentityUnavailableException if identity could not be extracted * @throws IdentityUnavailableException if identity could not be extracted
*/ */
public ObjectIdentityImpl(Object object) throws IdentityUnavailableException { public ObjectIdentityImpl(Object object) throws IdentityUnavailableException {
@ -84,13 +84,11 @@ public class ObjectIdentityImpl implements ObjectIdentity {
result = method.invoke(object); result = method.invoke(object);
} }
catch (Exception e) { catch (Exception e) {
throw new IdentityUnavailableException( throw new IdentityUnavailableException("Could not extract identity from object " + object, e);
"Could not extract identity from object " + object, e);
} }
Assert.notNull(result, "getId() is required to return a non-null value"); Assert.notNull(result, "getId() is required to return a non-null value");
Assert.isInstanceOf(Serializable.class, result, Assert.isInstanceOf(Serializable.class, result, "Getter must provide a return value of type Serializable");
"Getter must provide a return value of type Serializable");
this.identifier = (Serializable) result; this.identifier = (Serializable) result;
} }
@ -105,9 +103,7 @@ public class ObjectIdentityImpl implements ObjectIdentity {
* <p> * <p>
* Numeric identities (Integer and Long values) are considered equal if they are * Numeric identities (Integer and Long values) are considered equal if they are
* numerically equal. Other serializable types are evaluated using a simple equality. * numerically equal. Other serializable types are evaluated using a simple equality.
*
* @param arg0 object to compare * @param arg0 object to compare
*
* @return <code>true</code> if the presented object matches this object * @return <code>true</code> if the presented object matches this object
*/ */
@Override @Override
@ -120,8 +116,7 @@ public class ObjectIdentityImpl implements ObjectIdentity {
if (identifier instanceof Number && other.identifier instanceof Number) { if (identifier instanceof Number && other.identifier instanceof Number) {
// Integers and Longs with same value should be considered equal // Integers and Longs with same value should be considered equal
if (((Number) identifier).longValue() != ((Number) other.identifier) if (((Number) identifier).longValue() != ((Number) other.identifier).longValue()) {
.longValue()) {
return false; return false;
} }
} }
@ -147,7 +142,6 @@ public class ObjectIdentityImpl implements ObjectIdentity {
/** /**
* Important so caching operates properly. * Important so caching operates properly.
*
* @return the hash * @return the hash
*/ */
@Override @Override
@ -166,4 +160,5 @@ public class ObjectIdentityImpl implements ObjectIdentity {
return sb.toString(); return sb.toString();
} }
} }

View File

@ -29,8 +29,8 @@ import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
* *
* @author Ben Alex * @author Ben Alex
*/ */
public class ObjectIdentityRetrievalStrategyImpl implements public class ObjectIdentityRetrievalStrategyImpl implements ObjectIdentityRetrievalStrategy, ObjectIdentityGenerator {
ObjectIdentityRetrievalStrategy, ObjectIdentityGenerator {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
@ -41,4 +41,5 @@ public class ObjectIdentityRetrievalStrategyImpl implements
public ObjectIdentity createObjectIdentity(Serializable id, String type) { public ObjectIdentity createObjectIdentity(Serializable id, String type) {
return new ObjectIdentityImpl(type, id); return new ObjectIdentityImpl(type, id);
} }
} }

View File

@ -32,9 +32,7 @@ public interface PermissionFactory {
/** /**
* Dynamically creates a <code>CumulativePermission</code> or * Dynamically creates a <code>CumulativePermission</code> or
* <code>BasePermission</code> representing the active bits in the passed mask. * <code>BasePermission</code> representing the active bits in the passed mask.
*
* @param mask to build * @param mask to build
*
* @return a Permission representing the requested object * @return a Permission representing the requested object
*/ */
Permission buildFromMask(int mask); Permission buildFromMask(int mask);
@ -42,4 +40,5 @@ public interface PermissionFactory {
Permission buildFromName(String name); Permission buildFromName(String name);
List<Permission> buildFromNames(List<String> names); List<Permission> buildFromNames(List<String> names);
} }

View File

@ -31,6 +31,7 @@ import org.springframework.util.Assert;
* @author Ben Alex * @author Ben Alex
*/ */
public class PrincipalSid implements Sid { public class PrincipalSid implements Sid {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
@ -78,4 +79,5 @@ public class PrincipalSid implements Sid {
public String toString() { public String toString() {
return "PrincipalSid[" + this.principal + "]"; return "PrincipalSid[" + this.principal + "]";
} }
} }

View File

@ -67,4 +67,5 @@ public class SidRetrievalStrategyImpl implements SidRetrievalStrategy {
return sids; return sids;
} }
} }

View File

@ -39,18 +39,20 @@ import java.io.Serializable;
* @since 3.2 * @since 3.2
*/ */
public class SpringCacheBasedAclCache implements AclCache { public class SpringCacheBasedAclCache implements AclCache {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private final Cache cache; private final Cache cache;
private PermissionGrantingStrategy permissionGrantingStrategy; private PermissionGrantingStrategy permissionGrantingStrategy;
private AclAuthorizationStrategy aclAuthorizationStrategy; private AclAuthorizationStrategy aclAuthorizationStrategy;
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
public SpringCacheBasedAclCache(Cache cache, public SpringCacheBasedAclCache(Cache cache, PermissionGrantingStrategy permissionGrantingStrategy,
PermissionGrantingStrategy permissionGrantingStrategy,
AclAuthorizationStrategy aclAuthorizationStrategy) { AclAuthorizationStrategy aclAuthorizationStrategy) {
Assert.notNull(cache, "Cache required"); Assert.notNull(cache, "Cache required");
Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required"); Assert.notNull(permissionGrantingStrategy, "PermissionGrantingStrategy required");
@ -120,10 +122,8 @@ public class SpringCacheBasedAclCache implements AclCache {
private MutableAcl initializeTransientFields(MutableAcl value) { private MutableAcl initializeTransientFields(MutableAcl value) {
if (value instanceof AclImpl) { if (value instanceof AclImpl) {
FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, FieldUtils.setProtectedFieldValue("aclAuthorizationStrategy", value, this.aclAuthorizationStrategy);
this.aclAuthorizationStrategy); FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value, this.permissionGrantingStrategy);
FieldUtils.setProtectedFieldValue("permissionGrantingStrategy", value,
this.permissionGrantingStrategy);
} }
if (value.getParentAcl() != null) { if (value.getParentAcl() != null) {
@ -135,4 +135,5 @@ public class SpringCacheBasedAclCache implements AclCache {
public void clearCache() { public void clearCache() {
cache.clear(); cache.clear();
} }
} }

View File

@ -17,4 +17,3 @@
* Basic implementation of access control lists (ACLs) interfaces. * Basic implementation of access control lists (ACLs) interfaces.
*/ */
package org.springframework.security.acls.domain; package org.springframework.security.acls.domain;

View File

@ -31,12 +31,16 @@ import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Utility class for helping convert database representations of {@link ObjectIdentity#getIdentifier()} into * Utility class for helping convert database representations of
* the correct Java type as specified by <code>acl_class.class_id_type</code>. * {@link ObjectIdentity#getIdentifier()} into the correct Java type as specified by
* <code>acl_class.class_id_type</code>.
*
* @author paulwheeler * @author paulwheeler
*/ */
class AclClassIdUtils { class AclClassIdUtils {
private static final String DEFAULT_CLASS_ID_TYPE_COLUMN_NAME = "class_id_type"; private static final String DEFAULT_CLASS_ID_TYPE_COLUMN_NAME = "class_id_type";
private static final Log log = LogFactory.getLog(AclClassIdUtils.class); private static final Log log = LogFactory.getLog(AclClassIdUtils.class);
private ConversionService conversionService; private ConversionService conversionService;
@ -54,19 +58,20 @@ class AclClassIdUtils {
} }
/** /**
* Converts the raw type from the database into the right Java type. For most applications the 'raw type' will be Long, for some applications * Converts the raw type from the database into the right Java type. For most
* it could be String. * applications the 'raw type' will be Long, for some applications it could be String.
* @param identifier The identifier from the database * @param identifier The identifier from the database
* @param resultSet Result set of the query * @param resultSet Result set of the query
* @return The identifier in the appropriate target Java type. Typically Long or UUID. * @return The identifier in the appropriate target Java type. Typically Long or UUID.
* @throws SQLException * @throws SQLException
*/ */
Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException { Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
if (isString(identifier) && hasValidClassIdType(resultSet) if (isString(identifier) && hasValidClassIdType(resultSet)
&& canConvertFromStringTo(classIdTypeFrom(resultSet))) { && canConvertFromStringTo(classIdTypeFrom(resultSet))) {
identifier = convertFromStringTo((String) identifier, classIdTypeFrom(resultSet)); identifier = convertFromStringTo((String) identifier, classIdTypeFrom(resultSet));
} else { }
else {
// Assume it should be a Long type // Assume it should be a Long type
identifier = convertToLong(identifier); identifier = convertToLong(identifier);
} }
@ -78,13 +83,14 @@ class AclClassIdUtils {
boolean hasClassIdType = false; boolean hasClassIdType = false;
try { try {
hasClassIdType = classIdTypeFrom(resultSet) != null; hasClassIdType = classIdTypeFrom(resultSet) != null;
} catch (SQLException e) { }
catch (SQLException e) {
log.debug("Unable to obtain the class id type", e); log.debug("Unable to obtain the class id type", e);
} }
return hasClassIdType; return hasClassIdType;
} }
private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException { private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet) throws SQLException {
return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME)); return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
} }
@ -93,7 +99,8 @@ class AclClassIdUtils {
if (className != null) { if (className != null) {
try { try {
targetType = Class.forName(className); targetType = Class.forName(className);
} catch (ClassNotFoundException e) { }
catch (ClassNotFoundException e) {
log.debug("Unable to find class id type on classpath", e); log.debug("Unable to find class id type on classpath", e);
} }
} }
@ -109,18 +116,21 @@ class AclClassIdUtils {
} }
/** /**
* Converts to a {@link Long}, attempting to use the {@link ConversionService} if available. * Converts to a {@link Long}, attempting to use the {@link ConversionService} if
* @param identifier The identifier * available.
* @param identifier The identifier
* @return Long version of the identifier * @return Long version of the identifier
* @throws NumberFormatException if the string cannot be parsed to a long. * @throws NumberFormatException if the string cannot be parsed to a long.
* @throws org.springframework.core.convert.ConversionException if a conversion exception occurred * @throws org.springframework.core.convert.ConversionException if a conversion
* exception occurred
* @throws IllegalArgumentException if targetType is null * @throws IllegalArgumentException if targetType is null
*/ */
private Long convertToLong(Serializable identifier) { private Long convertToLong(Serializable identifier) {
Long idAsLong; Long idAsLong;
if (conversionService.canConvert(identifier.getClass(), Long.class)) { if (conversionService.canConvert(identifier.getClass(), Long.class)) {
idAsLong = conversionService.convert(identifier, Long.class); idAsLong = conversionService.convert(identifier, Long.class);
} else { }
else {
idAsLong = Long.valueOf(identifier.toString()); idAsLong = Long.valueOf(identifier.toString());
} }
return idAsLong; return idAsLong;
@ -136,6 +146,7 @@ class AclClassIdUtils {
} }
private static class StringToLongConverter implements Converter<String, Long> { private static class StringToLongConverter implements Converter<String, Long> {
@Override @Override
public Long convert(String identifierAsString) { public Long convert(String identifierAsString) {
if (identifierAsString == null) { if (identifierAsString == null) {
@ -145,9 +156,11 @@ class AclClassIdUtils {
} }
return Long.parseLong(identifierAsString); return Long.parseLong(identifierAsString);
} }
} }
private static class StringToUUIDConverter implements Converter<String, UUID> { private static class StringToUUIDConverter implements Converter<String, UUID> {
@Override @Override
public UUID convert(String identifierAsString) { public UUID convert(String identifierAsString) {
if (identifierAsString == null) { if (identifierAsString == null) {
@ -157,5 +170,7 @@ class AclClassIdUtils {
} }
return UUID.fromString(identifierAsString); return UUID.fromString(identifierAsString);
} }
} }
} }

View File

@ -68,9 +68,9 @@ import org.springframework.util.Assert;
* as it is likely to change in future releases and therefore subclassing is unsupported. * as it is likely to change in future releases and therefore subclassing is unsupported.
* <p> * <p>
* There are two SQL queries executed, one in the <tt>lookupPrimaryKeys</tt> method and * There are two SQL queries executed, one in the <tt>lookupPrimaryKeys</tt> method and
* one in <tt>lookupObjectIdentities</tt>. These are built from the same select and * one in <tt>lookupObjectIdentities</tt>. These are built from the same select and "order
* "order by" clause, using a different where clause in each case. In order to use custom * by" clause, using a different where clause in each case. In order to use custom schema
* schema or column names, each of these SQL clauses can be customized, but they must be * or column names, each of these SQL clauses can be customized, but they must be
* consistent with each other and with the expected result set generated by the the * consistent with each other and with the expected result set generated by the the
* default values. * default values.
* *
@ -79,21 +79,14 @@ import org.springframework.util.Assert;
public class BasicLookupStrategy implements LookupStrategy { public class BasicLookupStrategy implements LookupStrategy {
private final static String DEFAULT_SELECT_CLAUSE_COLUMNS = "select acl_object_identity.object_id_identity, " private final static String DEFAULT_SELECT_CLAUSE_COLUMNS = "select acl_object_identity.object_id_identity, "
+ "acl_entry.ace_order, " + "acl_entry.ace_order, " + "acl_object_identity.id as acl_id, " + "acl_object_identity.parent_object, "
+ "acl_object_identity.id as acl_id, " + "acl_object_identity.entries_inheriting, " + "acl_entry.id as ace_id, " + "acl_entry.mask, "
+ "acl_object_identity.parent_object, " + "acl_entry.granting, " + "acl_entry.audit_success, " + "acl_entry.audit_failure, "
+ "acl_object_identity.entries_inheriting, " + "acl_sid.principal as ace_principal, " + "acl_sid.sid as ace_sid, "
+ "acl_entry.id as ace_id, " + "acli_sid.principal as acl_principal, " + "acli_sid.sid as acl_sid, " + "acl_class.class ";
+ "acl_entry.mask, "
+ "acl_entry.granting, "
+ "acl_entry.audit_success, "
+ "acl_entry.audit_failure, "
+ "acl_sid.principal as ace_principal, "
+ "acl_sid.sid as ace_sid, "
+ "acli_sid.principal as acl_principal, "
+ "acli_sid.sid as acl_sid, "
+ "acl_class.class ";
private final static String DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN = ", acl_class.class_id_type "; private final static String DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN = ", acl_class.class_id_type ";
private final static String DEFAULT_SELECT_CLAUSE_FROM = "from acl_object_identity " private final static String DEFAULT_SELECT_CLAUSE_FROM = "from acl_object_identity "
+ "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid " + "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid "
+ "left join acl_class on acl_class.id = acl_object_identity.object_id_class " + "left join acl_class on acl_class.id = acl_object_identity.object_id_class "
@ -102,8 +95,8 @@ public class BasicLookupStrategy implements LookupStrategy {
public final static String DEFAULT_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS + DEFAULT_SELECT_CLAUSE_FROM; public final static String DEFAULT_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS + DEFAULT_SELECT_CLAUSE_FROM;
public final static String DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS + public final static String DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE = DEFAULT_SELECT_CLAUSE_COLUMNS
DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN + DEFAULT_SELECT_CLAUSE_FROM; + DEFAULT_SELECT_CLAUSE_ACL_CLASS_ID_TYPE_COLUMN + DEFAULT_SELECT_CLAUSE_FROM;
private final static String DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE = "(acl_object_identity.id = ?)"; private final static String DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE = "(acl_object_identity.id = ?)";
@ -116,20 +109,28 @@ public class BasicLookupStrategy implements LookupStrategy {
// ================================================================================================ // ================================================================================================
private final AclAuthorizationStrategy aclAuthorizationStrategy; private final AclAuthorizationStrategy aclAuthorizationStrategy;
private PermissionFactory permissionFactory = new DefaultPermissionFactory(); private PermissionFactory permissionFactory = new DefaultPermissionFactory();
private final AclCache aclCache; private final AclCache aclCache;
private final PermissionGrantingStrategy grantingStrategy; private final PermissionGrantingStrategy grantingStrategy;
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
private int batchSize = 50; private int batchSize = 50;
private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces"); private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class,
"acl"); private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl");
// SQL Customization fields // SQL Customization fields
private String selectClause = DEFAULT_SELECT_CLAUSE; private String selectClause = DEFAULT_SELECT_CLAUSE;
private String lookupPrimaryKeysWhereClause = DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE; private String lookupPrimaryKeysWhereClause = DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE;
private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE; private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE;
private String orderByClause = DEFAULT_ORDER_BY_CLAUSE; private String orderByClause = DEFAULT_ORDER_BY_CLAUSE;
private AclClassIdUtils aclClassIdUtils; private AclClassIdUtils aclClassIdUtils;
@ -139,28 +140,24 @@ public class BasicLookupStrategy implements LookupStrategy {
/** /**
* Constructor accepting mandatory arguments * Constructor accepting mandatory arguments
*
* @param dataSource to access the database * @param dataSource to access the database
* @param aclCache the cache where fully-loaded elements can be stored * @param aclCache the cache where fully-loaded elements can be stored
* @param aclAuthorizationStrategy authorization strategy (required) * @param aclAuthorizationStrategy authorization strategy (required)
*/ */
public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) {
this(dataSource, aclCache, aclAuthorizationStrategy, this(dataSource, aclCache, aclAuthorizationStrategy, new DefaultPermissionGrantingStrategy(auditLogger));
new DefaultPermissionGrantingStrategy(auditLogger));
} }
/** /**
* Creates a new instance * Creates a new instance
*
* @param dataSource to access the database * @param dataSource to access the database
* @param aclCache the cache where fully-loaded elements can be stored * @param aclCache the cache where fully-loaded elements can be stored
* @param aclAuthorizationStrategy authorization strategy (required) * @param aclAuthorizationStrategy authorization strategy (required)
* @param grantingStrategy the PermissionGrantingStrategy * @param grantingStrategy the PermissionGrantingStrategy
*/ */
public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, public BasicLookupStrategy(DataSource dataSource, AclCache aclCache,
AclAuthorizationStrategy aclAuthorizationStrategy, AclAuthorizationStrategy aclAuthorizationStrategy, PermissionGrantingStrategy grantingStrategy) {
PermissionGrantingStrategy grantingStrategy) {
Assert.notNull(dataSource, "DataSource required"); Assert.notNull(dataSource, "DataSource required");
Assert.notNull(aclCache, "AclCache required"); Assert.notNull(aclCache, "AclCache required");
Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required");
@ -184,8 +181,8 @@ public class BasicLookupStrategy implements LookupStrategy {
final String endSql = orderByClause; final String endSql = orderByClause;
StringBuilder sqlStringBldr = new StringBuilder(startSql.length() StringBuilder sqlStringBldr = new StringBuilder(
+ endSql.length() + requiredRepetitions * (repeatingSql.length() + 4)); startSql.length() + endSql.length() + requiredRepetitions * (repeatingSql.length() + 4));
sqlStringBldr.append(startSql); sqlStringBldr.append(startSql);
for (int i = 1; i <= requiredRepetitions; i++) { for (int i = 1; i <= requiredRepetitions; i++) {
@ -216,8 +213,7 @@ public class BasicLookupStrategy implements LookupStrategy {
fieldAcl.set(ace, acl); fieldAcl.set(ace, acl);
} }
catch (IllegalAccessException e) { catch (IllegalAccessException e) {
throw new IllegalStateException( throw new IllegalStateException("Could not or set AclImpl on AccessControlEntryImpl fields", e);
"Could not or set AclImpl on AccessControlEntryImpl fields", e);
} }
} }
@ -233,27 +229,24 @@ public class BasicLookupStrategy implements LookupStrategy {
/** /**
* Locates the primary key IDs specified in "findNow", adding AclImpl instances with * Locates the primary key IDs specified in "findNow", adding AclImpl instances with
* StubAclParents to the "acls" Map. * StubAclParents to the "acls" Map.
*
* @param acls the AclImpls (with StubAclParents) * @param acls the AclImpls (with StubAclParents)
* @param findNow Long-based primary keys to retrieve * @param findNow Long-based primary keys to retrieve
* @param sids * @param sids
*/ */
private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, private void lookupPrimaryKeys(final Map<Serializable, Acl> acls, final Set<Long> findNow, final List<Sid> sids) {
final Set<Long> findNow, final List<Sid> sids) {
Assert.notNull(acls, "ACLs are required"); Assert.notNull(acls, "ACLs are required");
Assert.notEmpty(findNow, "Items to find now required"); Assert.notEmpty(findNow, "Items to find now required");
String sql = computeRepeatingSql(lookupPrimaryKeysWhereClause, findNow.size()); String sql = computeRepeatingSql(lookupPrimaryKeysWhereClause, findNow.size());
Set<Long> parentsToLookup = jdbcTemplate.query(sql, Set<Long> parentsToLookup = jdbcTemplate.query(sql, ps -> {
ps -> { int i = 0;
int i = 0;
for (Long toFind : findNow) { for (Long toFind : findNow) {
i++; i++;
ps.setLong(i, toFind); ps.setLong(i, toFind);
} }
}, new ProcessResultSet(acls, sids)); }, new ProcessResultSet(acls, sids));
// Lookup the parents, now that our JdbcTemplate has released the database // Lookup the parents, now that our JdbcTemplate has released the database
// connection (SEC-547) // connection (SEC-547)
@ -271,28 +264,25 @@ public class BasicLookupStrategy implements LookupStrategy {
* develop a custom {@link LookupStrategy} implementation instead. * develop a custom {@link LookupStrategy} implementation instead.
* <p> * <p>
* The implementation works in batch sizes specified by {@link #batchSize}. * The implementation works in batch sizes specified by {@link #batchSize}.
*
* @param objects the identities to lookup (required) * @param objects the identities to lookup (required)
* @param sids the SIDs for which identities are required (ignored by this * @param sids the SIDs for which identities are required (ignored by this
* implementation) * implementation)
*
* @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the * @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the
* located {@link Acl} and values are the located {@link Acl} (never <tt>null</tt> * located {@link Acl} and values are the located {@link Acl} (never <tt>null</tt>
* although some entries may be missing; this method should not throw * although some entries may be missing; this method should not throw
* {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to * {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used to
* automatically create entries if required) * automatically create entries if required)
*/ */
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) {
List<Sid> sids) {
Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1"); Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1");
Assert.notEmpty(objects, "Objects to lookup required"); Assert.notEmpty(objects, "Objects to lookup required");
// Map<ObjectIdentity,Acl> // Map<ObjectIdentity,Acl>
Map<ObjectIdentity, Acl> result = new HashMap<>(); // contains Map<ObjectIdentity, Acl> result = new HashMap<>(); // contains
// FULLY // FULLY
// loaded // loaded
// Acl // Acl
// objects // objects
Set<ObjectIdentity> currentBatchToLoad = new HashSet<>(); Set<ObjectIdentity> currentBatchToLoad = new HashSet<>();
@ -330,11 +320,9 @@ public class BasicLookupStrategy implements LookupStrategy {
} }
// Is it time to load from JDBC the currentBatchToLoad? // Is it time to load from JDBC the currentBatchToLoad?
if ((currentBatchToLoad.size() == this.batchSize) if ((currentBatchToLoad.size() == this.batchSize) || ((i + 1) == objects.size())) {
|| ((i + 1) == objects.size())) {
if (currentBatchToLoad.size() > 0) { if (currentBatchToLoad.size() > 0) {
Map<ObjectIdentity, Acl> loadedBatch = lookupObjectIdentities( Map<ObjectIdentity, Acl> loadedBatch = lookupObjectIdentities(currentBatchToLoad, sids);
currentBatchToLoad, sids);
// Add loaded batch (all elements 100% initialized) to results // Add loaded batch (all elements 100% initialized) to results
result.putAll(loadedBatch); result.putAll(loadedBatch);
@ -364,37 +352,35 @@ public class BasicLookupStrategy implements LookupStrategy {
* properly-configured parent ACLs. * properly-configured parent ACLs.
* *
*/ */
private Map<ObjectIdentity, Acl> lookupObjectIdentities( private Map<ObjectIdentity, Acl> lookupObjectIdentities(final Collection<ObjectIdentity> objectIdentities,
final Collection<ObjectIdentity> objectIdentities, List<Sid> sids) { List<Sid> sids) {
Assert.notEmpty(objectIdentities, "Must provide identities to lookup"); Assert.notEmpty(objectIdentities, "Must provide identities to lookup");
final Map<Serializable, Acl> acls = new HashMap<>(); // contains final Map<Serializable, Acl> acls = new HashMap<>(); // contains
// Acls // Acls
// with // with
// StubAclParents // StubAclParents
// Make the "acls" map contain all requested objectIdentities // Make the "acls" map contain all requested objectIdentities
// (including markers to each parent in the hierarchy) // (including markers to each parent in the hierarchy)
String sql = computeRepeatingSql(lookupObjectIdentitiesWhereClause, String sql = computeRepeatingSql(lookupObjectIdentitiesWhereClause, objectIdentities.size());
objectIdentities.size());
Set<Long> parentsToLookup = jdbcTemplate.query(sql, Set<Long> parentsToLookup = jdbcTemplate.query(sql, ps -> {
ps -> { int i = 0;
int i = 0; for (ObjectIdentity oid : objectIdentities) {
for (ObjectIdentity oid : objectIdentities) { // Determine prepared statement values for this iteration
// Determine prepared statement values for this iteration String type = oid.getType();
String type = oid.getType();
// No need to check for nulls, as guaranteed non-null by // No need to check for nulls, as guaranteed non-null by
// ObjectIdentity.getIdentifier() interface contract // ObjectIdentity.getIdentifier() interface contract
String identifier = oid.getIdentifier().toString(); String identifier = oid.getIdentifier().toString();
// Inject values // Inject values
ps.setString((2 * i) + 1, identifier); ps.setString((2 * i) + 1, identifier);
ps.setString((2 * i) + 2, type); ps.setString((2 * i) + 2, type);
i++; i++;
} }
}, new ProcessResultSet(acls, sids)); }, new ProcessResultSet(acls, sids));
// Lookup the parents, now that our JdbcTemplate has released the database // Lookup the parents, now that our JdbcTemplate has released the database
// connection (SEC-547) // connection (SEC-547)
@ -406,10 +392,8 @@ public class BasicLookupStrategy implements LookupStrategy {
Map<ObjectIdentity, Acl> resultMap = new HashMap<>(); Map<ObjectIdentity, Acl> resultMap = new HashMap<>();
for (Acl inputAcl : acls.values()) { for (Acl inputAcl : acls.values()) {
Assert.isInstanceOf(AclImpl.class, inputAcl, Assert.isInstanceOf(AclImpl.class, inputAcl, "Map should have contained an AclImpl");
"Map should have contained an AclImpl"); Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(), "Acl.getId() must be Long");
Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(),
"Acl.getId() must be Long");
Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId()); Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId());
resultMap.put(result.getObjectIdentity(), result); resultMap.put(result.getObjectIdentity(), result);
@ -422,7 +406,6 @@ public class BasicLookupStrategy implements LookupStrategy {
* The final phase of converting the <code>Map</code> of <code>AclImpl</code> * The final phase of converting the <code>Map</code> of <code>AclImpl</code>
* instances which contain <code>StubAclParent</code>s into proper, valid * instances which contain <code>StubAclParent</code>s into proper, valid
* <code>AclImpl</code>s with correct ACL parents. * <code>AclImpl</code>s with correct ACL parents.
*
* @param inputMap the unconverted <code>AclImpl</code>s * @param inputMap the unconverted <code>AclImpl</code>s
* @param currentIdentity the current<code>Acl</code> that we wish to convert (this * @param currentIdentity the current<code>Acl</code> that we wish to convert (this
* may be * may be
@ -434,8 +417,7 @@ public class BasicLookupStrategy implements LookupStrategy {
// Retrieve this Acl from the InputMap // Retrieve this Acl from the InputMap
Acl uncastAcl = inputMap.get(currentIdentity); Acl uncastAcl = inputMap.get(currentIdentity);
Assert.isInstanceOf(AclImpl.class, uncastAcl, Assert.isInstanceOf(AclImpl.class, uncastAcl, "The inputMap contained a non-AclImpl");
"The inputMap contained a non-AclImpl");
AclImpl inputAcl = (AclImpl) uncastAcl; AclImpl inputAcl = (AclImpl) uncastAcl;
@ -448,9 +430,8 @@ public class BasicLookupStrategy implements LookupStrategy {
} }
// Now we have the parent (if there is one), create the true AclImpl // Now we have the parent (if there is one), create the true AclImpl
AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), inputAcl.getId(), aclAuthorizationStrategy,
inputAcl.getId(), aclAuthorizationStrategy, grantingStrategy, grantingStrategy, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner());
// Copy the "aces" from the input to the destination // Copy the "aces" from the input to the destination
@ -477,7 +458,6 @@ public class BasicLookupStrategy implements LookupStrategy {
/** /**
* Creates a particular implementation of {@link Sid} depending on the arguments. * Creates a particular implementation of {@link Sid} depending on the arguments.
*
* @param sid the name of the sid representing its unique identifier. In typical ACL * @param sid the name of the sid representing its unique identifier. In typical ACL
* database schema it's located in table {@code acl_sid} table, {@code sid} column. * database schema it's located in table {@code acl_sid} table, {@code sid} column.
* @param isPrincipal whether it's a user or granted authority like role * @param isPrincipal whether it's a user or granted authority like role
@ -496,7 +476,6 @@ public class BasicLookupStrategy implements LookupStrategy {
* Sets the {@code PermissionFactory} instance which will be used to convert loaded * Sets the {@code PermissionFactory} instance which will be used to convert loaded
* permission data values to {@code Permission}s. A {@code DefaultPermissionFactory} * permission data values to {@code Permission}s. A {@code DefaultPermissionFactory}
* will be used by default. * will be used by default.
*
* @param permissionFactory * @param permissionFactory
*/ */
public final void setPermissionFactory(PermissionFactory permissionFactory) { public final void setPermissionFactory(PermissionFactory permissionFactory) {
@ -510,7 +489,6 @@ public class BasicLookupStrategy implements LookupStrategy {
/** /**
* The SQL for the select clause. If customizing in order to modify column names, * The SQL for the select clause. If customizing in order to modify column names,
* schema etc, the other SQL customization fields must also be set to match. * schema etc, the other SQL customization fields must also be set to match.
*
* @param selectClause the select clause, which defaults to * @param selectClause the select clause, which defaults to
* {@link #DEFAULT_SELECT_CLAUSE}. * {@link #DEFAULT_SELECT_CLAUSE}.
*/ */
@ -528,8 +506,7 @@ public class BasicLookupStrategy implements LookupStrategy {
/** /**
* The SQL for the where clause used in the <tt>lookupObjectIdentities</tt> method. * The SQL for the where clause used in the <tt>lookupObjectIdentities</tt> method.
*/ */
public final void setLookupObjectIdentitiesWhereClause( public final void setLookupObjectIdentitiesWhereClause(String lookupObjectIdentitiesWhereClause) {
String lookupObjectIdentitiesWhereClause) {
this.lookupObjectIdentitiesWhereClause = lookupObjectIdentitiesWhereClause; this.lookupObjectIdentitiesWhereClause = lookupObjectIdentitiesWhereClause;
} }
@ -542,8 +519,9 @@ public class BasicLookupStrategy implements LookupStrategy {
public final void setAclClassIdSupported(boolean aclClassIdSupported) { public final void setAclClassIdSupported(boolean aclClassIdSupported) {
if (aclClassIdSupported) { if (aclClassIdSupported) {
Assert.isTrue(this.selectClause.equals(DEFAULT_SELECT_CLAUSE), "Cannot set aclClassIdSupported and override the select clause; " Assert.isTrue(this.selectClause.equals(DEFAULT_SELECT_CLAUSE),
+ "just override the select clause"); "Cannot set aclClassIdSupported and override the select clause; "
+ "just override the select clause");
this.selectClause = DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE; this.selectClause = DEFAULT_ACL_CLASS_ID_SELECT_CLAUSE;
} }
} }
@ -556,7 +534,9 @@ public class BasicLookupStrategy implements LookupStrategy {
// ================================================================================================== // ==================================================================================================
private class ProcessResultSet implements ResultSetExtractor<Set<Long>> { private class ProcessResultSet implements ResultSetExtractor<Set<Long>> {
private final Map<Serializable, Acl> acls; private final Map<Serializable, Acl> acls;
private final List<Sid> sids; private final List<Sid> sids;
ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) { ProcessResultSet(Map<Serializable, Acl> acls, List<Sid> sids) {
@ -612,15 +592,12 @@ public class BasicLookupStrategy implements LookupStrategy {
/** /**
* Accepts the current <code>ResultSet</code> row, and converts it into an * Accepts the current <code>ResultSet</code> row, and converts it into an
* <code>AclImpl</code> that contains a <code>StubAclParent</code> * <code>AclImpl</code> that contains a <code>StubAclParent</code>
*
* @param acls the Map we should add the converted Acl to * @param acls the Map we should add the converted Acl to
* @param rs the ResultSet focused on a current row * @param rs the ResultSet focused on a current row
*
* @throws SQLException if something goes wrong converting values * @throws SQLException if something goes wrong converting values
* @throws ConversionException if can't convert to the desired Java type * @throws ConversionException if can't convert to the desired Java type
*/ */
private void convertCurrentResultIntoObject(Map<Serializable, Acl> acls, private void convertCurrentResultIntoObject(Map<Serializable, Acl> acls, ResultSet rs) throws SQLException {
ResultSet rs) throws SQLException {
Long id = rs.getLong("acl_id"); Long id = rs.getLong("acl_id");
// If we already have an ACL for this ID, just create the ACE // If we already have an ACL for this ID, just create the ACE
@ -629,11 +606,11 @@ public class BasicLookupStrategy implements LookupStrategy {
if (acl == null) { if (acl == null) {
// Make an AclImpl and pop it into the Map // Make an AclImpl and pop it into the Map
// If the Java type is a String, check to see if we can convert it to the target id type, e.g. UUID. // If the Java type is a String, check to see if we can convert it to the
// target id type, e.g. UUID.
Serializable identifier = (Serializable) rs.getObject("object_id_identity"); Serializable identifier = (Serializable) rs.getObject("object_id_identity");
identifier = aclClassIdUtils.identifierFrom(identifier, rs); identifier = aclClassIdUtils.identifierFrom(identifier, rs);
ObjectIdentity objectIdentity = new ObjectIdentityImpl( ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("class"), identifier);
rs.getString("class"), identifier);
Acl parentAcl = null; Acl parentAcl = null;
long parentAclId = rs.getLong("parent_object"); long parentAclId = rs.getLong("parent_object");
@ -643,11 +620,10 @@ public class BasicLookupStrategy implements LookupStrategy {
} }
boolean entriesInheriting = rs.getBoolean("entries_inheriting"); boolean entriesInheriting = rs.getBoolean("entries_inheriting");
Sid owner = createSid(rs.getBoolean("acl_principal"), Sid owner = createSid(rs.getBoolean("acl_principal"), rs.getString("acl_sid"));
rs.getString("acl_sid"));
acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, grantingStrategy, parentAcl, null,
grantingStrategy, parentAcl, null, entriesInheriting, owner); entriesInheriting, owner);
acls.put(id, acl); acls.put(id, acl);
} }
@ -657,8 +633,7 @@ public class BasicLookupStrategy implements LookupStrategy {
// ACE_SID) // ACE_SID)
if (rs.getString("ace_sid") != null) { if (rs.getString("ace_sid") != null) {
Long aceId = rs.getLong("ace_id"); Long aceId = rs.getLong("ace_id");
Sid recipient = createSid(rs.getBoolean("ace_principal"), Sid recipient = createSid(rs.getBoolean("ace_principal"), rs.getString("ace_sid"));
rs.getString("ace_sid"));
int mask = rs.getInt("mask"); int mask = rs.getInt("mask");
Permission permission = permissionFactory.buildFromMask(mask); Permission permission = permissionFactory.buildFromMask(mask);
@ -666,8 +641,8 @@ public class BasicLookupStrategy implements LookupStrategy {
boolean auditSuccess = rs.getBoolean("audit_success"); boolean auditSuccess = rs.getBoolean("audit_success");
boolean auditFailure = rs.getBoolean("audit_failure"); boolean auditFailure = rs.getBoolean("audit_failure");
AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting,
recipient, permission, granting, auditSuccess, auditFailure); auditSuccess, auditFailure);
// Field acesField = FieldUtils.getField(AclImpl.class, "aces"); // Field acesField = FieldUtils.getField(AclImpl.class, "aces");
List<AccessControlEntryImpl> aces = readAces((AclImpl) acl); List<AccessControlEntryImpl> aces = readAces((AclImpl) acl);
@ -678,9 +653,11 @@ public class BasicLookupStrategy implements LookupStrategy {
} }
} }
} }
} }
private static class StubAclParent implements Acl { private static class StubAclParent implements Acl {
private final Long id; private final Long id;
StubAclParent(Long id) { StubAclParent(Long id) {
@ -711,14 +688,15 @@ public class BasicLookupStrategy implements LookupStrategy {
throw new UnsupportedOperationException("Stub only"); throw new UnsupportedOperationException("Stub only");
} }
public boolean isGranted(List<Permission> permission, List<Sid> sids, public boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
boolean administrativeMode) throws NotFoundException, throws NotFoundException, UnloadedSidException {
UnloadedSidException {
throw new UnsupportedOperationException("Stub only"); throw new UnsupportedOperationException("Stub only");
} }
public boolean isSidLoaded(List<Sid> sids) { public boolean isSidLoaded(List<Sid> sids) {
throw new UnsupportedOperationException("Stub only"); throw new UnsupportedOperationException("Stub only");
} }
} }
} }

View File

@ -45,18 +45,26 @@ import org.springframework.util.Assert;
* @author Ben Alex * @author Ben Alex
*/ */
public class JdbcAclService implements AclService { public class JdbcAclService implements AclService {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
protected static final Log log = LogFactory.getLog(JdbcAclService.class); protected static final Log log = LogFactory.getLog(JdbcAclService.class);
private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS = "class.class as class"; private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS = "class.class as class";
private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE = DEFAULT_SELECT_ACL_CLASS_COLUMNS + ", class.class_id_type as class_id_type";
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, " + DEFAULT_SELECT_ACL_CLASS_COLUMNS private static final String DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE = DEFAULT_SELECT_ACL_CLASS_COLUMNS
+ ", class.class_id_type as class_id_type";
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL = "select obj.object_id_identity as obj_id, "
+ DEFAULT_SELECT_ACL_CLASS_COLUMNS
+ " from acl_object_identity obj, acl_object_identity parent, acl_class class " + " from acl_object_identity obj, acl_object_identity parent, acl_class class "
+ "where obj.parent_object = parent.id and obj.object_id_class = class.id " + "where obj.parent_object = parent.id and obj.object_id_class = class.id "
+ "and parent.object_id_identity = ? and parent.object_id_class = (" + "and parent.object_id_identity = ? and parent.object_id_class = ("
+ "select id FROM acl_class where acl_class.class = ?)"; + "select id FROM acl_class where acl_class.class = ?)";
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE = "select obj.object_id_identity as obj_id, " + DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE
private static final String DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE = "select obj.object_id_identity as obj_id, "
+ DEFAULT_SELECT_ACL_CLASS_COLUMNS_WITH_ID_TYPE
+ " from acl_object_identity obj, acl_object_identity parent, acl_class class " + " from acl_object_identity obj, acl_object_identity parent, acl_class class "
+ "where obj.parent_object = parent.id and obj.object_id_class = class.id " + "where obj.parent_object = parent.id and obj.object_id_class = class.id "
+ "and parent.object_id_identity = ? and parent.object_id_class = (" + "and parent.object_id_identity = ? and parent.object_id_class = ("
@ -66,9 +74,13 @@ public class JdbcAclService implements AclService {
// ================================================================================================ // ================================================================================================
protected final JdbcOperations jdbcOperations; protected final JdbcOperations jdbcOperations;
private final LookupStrategy lookupStrategy; private final LookupStrategy lookupStrategy;
private boolean aclClassIdSupported; private boolean aclClassIdSupported;
private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL; private String findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL;
private AclClassIdUtils aclClassIdUtils; private AclClassIdUtils aclClassIdUtils;
// ~ Constructors // ~ Constructors
@ -91,13 +103,12 @@ public class JdbcAclService implements AclService {
public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) { public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() }; Object[] args = { parentIdentity.getIdentifier().toString(), parentIdentity.getType() };
List<ObjectIdentity> objects = jdbcOperations.query(findChildrenSql, args, List<ObjectIdentity> objects = jdbcOperations.query(findChildrenSql, args, (rs, rowNum) -> {
(rs, rowNum) -> { String javaType = rs.getString("class");
String javaType = rs.getString("class"); Serializable identifier = (Serializable) rs.getObject("obj_id");
Serializable identifier = (Serializable) rs.getObject("obj_id"); identifier = aclClassIdUtils.identifierFrom(identifier, rs);
identifier = aclClassIdUtils.identifierFrom(identifier, rs); return new ObjectIdentityImpl(javaType, identifier);
return new ObjectIdentityImpl(javaType, identifier); });
});
if (objects.isEmpty()) { if (objects.isEmpty()) {
return null; return null;
@ -106,8 +117,7 @@ public class JdbcAclService implements AclService {
return objects; return objects;
} }
public Acl readAclById(ObjectIdentity object, List<Sid> sids) public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
throws NotFoundException {
Map<ObjectIdentity, Acl> map = readAclsById(Collections.singletonList(object), sids); Map<ObjectIdentity, Acl> map = readAclsById(Collections.singletonList(object), sids);
Assert.isTrue(map.containsKey(object), Assert.isTrue(map.containsKey(object),
() -> "There should have been an Acl entry for ObjectIdentity " + object); () -> "There should have been an Acl entry for ObjectIdentity " + object);
@ -119,22 +129,19 @@ public class JdbcAclService implements AclService {
return readAclById(object, null); return readAclById(object, null);
} }
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException {
throws NotFoundException {
return readAclsById(objects, null); return readAclsById(objects, null);
} }
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
List<Sid> sids) throws NotFoundException { throws NotFoundException {
Map<ObjectIdentity, Acl> result = lookupStrategy.readAclsById(objects, sids); Map<ObjectIdentity, Acl> result = lookupStrategy.readAclsById(objects, sids);
// Check every requested object identity was found (throw NotFoundException if // Check every requested object identity was found (throw NotFoundException if
// needed) // needed)
for (ObjectIdentity oid : objects) { for (ObjectIdentity oid : objects) {
if (!result.containsKey(oid)) { if (!result.containsKey(oid)) {
throw new NotFoundException( throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'");
"Unable to find ACL information for object identity '" + oid
+ "'");
} }
} }
@ -143,7 +150,6 @@ public class JdbcAclService implements AclService {
/** /**
* Allows customization of the SQL query used to find child object identities. * Allows customization of the SQL query used to find child object identities.
*
* @param findChildrenSql * @param findChildrenSql
*/ */
public void setFindChildrenQuery(String findChildrenSql) { public void setFindChildrenQuery(String findChildrenSql) {
@ -156,7 +162,8 @@ public class JdbcAclService implements AclService {
// Change the default children select if it hasn't been overridden // Change the default children select if it hasn't been overridden
if (this.findChildrenSql.equals(DEFAULT_SELECT_ACL_WITH_PARENT_SQL)) { if (this.findChildrenSql.equals(DEFAULT_SELECT_ACL_WITH_PARENT_SQL)) {
this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE; this.findChildrenSql = DEFAULT_SELECT_ACL_WITH_PARENT_SQL_WITH_CLASS_ID_TYPE;
} else { }
else {
log.debug("Find children statement has already been overridden, so not overridding the default"); log.debug("Find children statement has already been overridden, so not overridding the default");
} }
} }
@ -169,4 +176,5 @@ public class JdbcAclService implements AclService {
protected boolean isAclClassIdSupported() { protected boolean isAclClassIdSupported() {
return aclClassIdSupported; return aclClassIdSupported;
} }
} }

View File

@ -58,39 +58,52 @@ import org.springframework.util.Assert;
* @author Johannes Zlattinger * @author Johannes Zlattinger
*/ */
public class JdbcMutableAclService extends JdbcAclService implements MutableAclService { public class JdbcMutableAclService extends JdbcAclService implements MutableAclService {
private static final String DEFAULT_INSERT_INTO_ACL_CLASS = "insert into acl_class (class) values (?)"; private static final String DEFAULT_INSERT_INTO_ACL_CLASS = "insert into acl_class (class) values (?)";
private static final String DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID = "insert into acl_class (class, class_id_type) values (?, ?)"; private static final String DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID = "insert into acl_class (class, class_id_type) values (?, ?)";
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private boolean foreignKeysInDatabase = true; private boolean foreignKeysInDatabase = true;
private final AclCache aclCache; private final AclCache aclCache;
private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?"; private String deleteEntryByObjectIdentityForeignKey = "delete from acl_entry where acl_object_identity=?";
private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?"; private String deleteObjectIdentityByPrimaryKey = "delete from acl_object_identity where id=?";
private String classIdentityQuery = "call identity()"; private String classIdentityQuery = "call identity()";
private String sidIdentityQuery = "call identity()"; private String sidIdentityQuery = "call identity()";
private String insertClass = DEFAULT_INSERT_INTO_ACL_CLASS; private String insertClass = DEFAULT_INSERT_INTO_ACL_CLASS;
private String insertEntry = "insert into acl_entry " private String insertEntry = "insert into acl_entry "
+ "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)" + "(acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)"
+ "values (?, ?, ?, ?, ?, ?, ?)"; + "values (?, ?, ?, ?, ?, ?, ?)";
private String insertObjectIdentity = "insert into acl_object_identity " private String insertObjectIdentity = "insert into acl_object_identity "
+ "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "(object_id_class, object_id_identity, owner_sid, entries_inheriting) " + "values (?, ?, ?, ?)";
+ "values (?, ?, ?, ?)";
private String insertSid = "insert into acl_sid (principal, sid) values (?, ?)"; private String insertSid = "insert into acl_sid (principal, sid) values (?, ?)";
private String selectClassPrimaryKey = "select id from acl_class where class=?"; private String selectClassPrimaryKey = "select id from acl_class where class=?";
private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class " private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class "
+ "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? " + "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? "
+ "and acl_object_identity.object_id_identity = ?"; + "and acl_object_identity.object_id_identity = ?";
private String selectSidPrimaryKey = "select id from acl_sid where principal=? and sid=?"; private String selectSidPrimaryKey = "select id from acl_sid where principal=? and sid=?";
private String updateObjectIdentity = "update acl_object_identity set " private String updateObjectIdentity = "update acl_object_identity set "
+ "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + "parent_object = ?, owner_sid = ?, entries_inheriting = ?" + " where id = ?";
+ " where id = ?";
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, public JdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
AclCache aclCache) {
super(dataSource, lookupStrategy); super(dataSource, lookupStrategy);
Assert.notNull(aclCache, "AclCache required"); Assert.notNull(aclCache, "AclCache required");
this.aclCache = aclCache; this.aclCache = aclCache;
@ -99,14 +112,12 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
public MutableAcl createAcl(ObjectIdentity objectIdentity) public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException {
throws AlreadyExistsException {
Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(objectIdentity, "Object Identity required");
// Check this object identity hasn't already been persisted // Check this object identity hasn't already been persisted
if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) { if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) {
throw new AlreadyExistsException("Object identity '" + objectIdentity throw new AlreadyExistsException("Object identity '" + objectIdentity + "' already exists");
+ "' already exists");
} }
// Need to retrieve the current principal, in order to know who "owns" this ACL // Need to retrieve the current principal, in order to know who "owns" this ACL
@ -128,7 +139,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
/** /**
* Creates a new row in acl_entry for every ACE defined in the passed MutableAcl * Creates a new row in acl_entry for every ACE defined in the passed MutableAcl
* object. * object.
*
* @param acl containing the ACEs to insert * @param acl containing the ACEs to insert
*/ */
protected void createEntries(final MutableAcl acl) { protected void createEntries(final MutableAcl acl) {
@ -142,8 +152,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
public void setValues(PreparedStatement stmt, int i) throws SQLException { public void setValues(PreparedStatement stmt, int i) throws SQLException {
AccessControlEntry entry_ = acl.getEntries().get(i); AccessControlEntry entry_ = acl.getEntries().get(i);
Assert.isTrue(entry_ instanceof AccessControlEntryImpl, Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class");
"Unknown ACE class");
AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_; AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
stmt.setLong(1, (Long) acl.getId()); stmt.setLong(1, (Long) acl.getId());
@ -161,7 +170,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* Creates an entry in the acl_object_identity table for the passed ObjectIdentity. * Creates an entry in the acl_object_identity table for the passed ObjectIdentity.
* The Sid is also necessary, as acl_object_identity has defined the sid column as * The Sid is also necessary, as acl_object_identity has defined the sid column as
* non-null. * non-null.
*
* @param object to represent an acl_object_identity for * @param object to represent an acl_object_identity for
* @param owner for the SID column (will be created if there is no acl_sid entry for * @param owner for the SID column (will be created if there is no acl_sid entry for
* this particular Sid already) * this particular Sid already)
@ -169,22 +177,18 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
protected void createObjectIdentity(ObjectIdentity object, Sid owner) { protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
Long sidId = createOrRetrieveSidPrimaryKey(owner, true); Long sidId = createOrRetrieveSidPrimaryKey(owner, true);
Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true, object.getIdentifier().getClass()); Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true, object.getIdentifier().getClass());
jdbcOperations.update(insertObjectIdentity, classId, object.getIdentifier().toString(), sidId, jdbcOperations.update(insertObjectIdentity, classId, object.getIdentifier().toString(), sidId, Boolean.TRUE);
Boolean.TRUE);
} }
/** /**
* Retrieves the primary key from {@code acl_class}, creating a new row if needed and * Retrieves the primary key from {@code acl_class}, creating a new row if needed and
* the {@code allowCreate} property is {@code true}. * the {@code allowCreate} property is {@code true}.
*
* @param type to find or create an entry for (often the fully-qualified class name) * @param type to find or create an entry for (often the fully-qualified class name)
* @param allowCreate true if creation is permitted if not found * @param allowCreate true if creation is permitted if not found
*
* @return the primary key or null if not found * @return the primary key or null if not found
*/ */
protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) { protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate, Class idType) {
List<Long> classIds = jdbcOperations.queryForList(selectClassPrimaryKey, List<Long> classIds = jdbcOperations.queryForList(selectClassPrimaryKey, new Object[] { type }, Long.class);
new Object[] { type }, Long.class);
if (!classIds.isEmpty()) { if (!classIds.isEmpty()) {
return classIds.get(0); return classIds.get(0);
@ -193,11 +197,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
if (allowCreate) { if (allowCreate) {
if (!isAclClassIdSupported()) { if (!isAclClassIdSupported()) {
jdbcOperations.update(insertClass, type); jdbcOperations.update(insertClass, type);
} else { }
else {
jdbcOperations.update(insertClass, type, idType.getCanonicalName()); jdbcOperations.update(insertClass, type, idType.getCanonicalName());
} }
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
"Transaction must be running");
return jdbcOperations.queryForObject(classIdentityQuery, Long.class); return jdbcOperations.queryForObject(classIdentityQuery, Long.class);
} }
@ -207,12 +211,9 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
/** /**
* Retrieves the primary key from acl_sid, creating a new row if needed and the * Retrieves the primary key from acl_sid, creating a new row if needed and the
* allowCreate property is true. * allowCreate property is true.
*
* @param sid to find or create * @param sid to find or create
* @param allowCreate true if creation is permitted if not found * @param allowCreate true if creation is permitted if not found
*
* @return the primary key or null if not found * @return the primary key or null if not found
*
* @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized * @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized
* implementation. * implementation.
*/ */
@ -244,11 +245,10 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* @param allowCreate true if creation is permitted if not found * @param allowCreate true if creation is permitted if not found
* @return the primary key or null if not found * @return the primary key or null if not found
*/ */
protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) {
boolean allowCreate) {
List<Long> sidIds = jdbcOperations.queryForList(selectSidPrimaryKey, new Object[] { List<Long> sidIds = jdbcOperations.queryForList(selectSidPrimaryKey, new Object[] { sidIsPrincipal, sidName },
sidIsPrincipal, sidName }, Long.class); Long.class);
if (!sidIds.isEmpty()) { if (!sidIds.isEmpty()) {
return sidIds.get(0); return sidIds.get(0);
@ -256,19 +256,16 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
if (allowCreate) { if (allowCreate) {
jdbcOperations.update(insertSid, sidIsPrincipal, sidName); jdbcOperations.update(insertSid, sidIsPrincipal, sidName);
Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running");
"Transaction must be running");
return jdbcOperations.queryForObject(sidIdentityQuery, Long.class); return jdbcOperations.queryForObject(sidIdentityQuery, Long.class);
} }
return null; return null;
} }
public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException {
throws ChildrenExistException {
Assert.notNull(objectIdentity, "Object Identity required"); Assert.notNull(objectIdentity, "Object Identity required");
Assert.notNull(objectIdentity.getIdentifier(), Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier");
"Object Identity doesn't provide an identifier");
if (deleteChildren) { if (deleteChildren) {
List<ObjectIdentity> children = findChildren(objectIdentity); List<ObjectIdentity> children = findChildren(objectIdentity);
@ -285,8 +282,8 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
// We generally don't do this, in the interests of deadlock management // We generally don't do this, in the interests of deadlock management
List<ObjectIdentity> children = findChildren(objectIdentity); List<ObjectIdentity> children = findChildren(objectIdentity);
if (children != null) { if (children != null) {
throw new ChildrenExistException("Cannot delete '" + objectIdentity throw new ChildrenExistException(
+ "' (has " + children.size() + " children)"); "Cannot delete '" + objectIdentity + "' (has " + children.size() + " children)");
} }
} }
} }
@ -306,7 +303,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
/** /**
* Deletes all ACEs defined in the acl_entry table belonging to the presented * Deletes all ACEs defined in the acl_entry table belonging to the presented
* ObjectIdentity primary key. * ObjectIdentity primary key.
*
* @param oidPrimaryKey the rows in acl_entry to delete * @param oidPrimaryKey the rows in acl_entry to delete
*/ */
protected void deleteEntries(Long oidPrimaryKey) { protected void deleteEntries(Long oidPrimaryKey) {
@ -319,7 +315,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* <p> * <p>
* We do not delete any entries from acl_class, even if no classes are using that * We do not delete any entries from acl_class, even if no classes are using that
* class any longer. This is a deadlock avoidance approach. * class any longer. This is a deadlock avoidance approach.
*
* @param oidPrimaryKey to delete the acl_object_identity * @param oidPrimaryKey to delete the acl_object_identity
*/ */
protected void deleteObjectIdentity(Long oidPrimaryKey) { protected void deleteObjectIdentity(Long oidPrimaryKey) {
@ -331,15 +326,13 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* Retrieves the primary key from the acl_object_identity table for the passed * Retrieves the primary key from the acl_object_identity table for the passed
* ObjectIdentity. Unlike some other methods in this implementation, this method will * ObjectIdentity. Unlike some other methods in this implementation, this method will
* NOT create a row (use {@link #createObjectIdentity(ObjectIdentity, Sid)} instead). * NOT create a row (use {@link #createObjectIdentity(ObjectIdentity, Sid)} instead).
*
* @param oid to find * @param oid to find
*
* @return the object identity or null if not found * @return the object identity or null if not found
*/ */
protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) { protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
try { try {
return jdbcOperations.queryForObject(selectObjectIdentityPrimaryKey, Long.class, return jdbcOperations.queryForObject(selectObjectIdentityPrimaryKey, Long.class, oid.getType(),
oid.getType(), oid.getIdentifier().toString()); oid.getIdentifier().toString());
} }
catch (DataAccessException notFound) { catch (DataAccessException notFound) {
return null; return null;
@ -387,29 +380,25 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
* Updates an existing acl_object_identity row, with new information presented in the * Updates an existing acl_object_identity row, with new information presented in the
* passed MutableAcl object. Also will create an acl_sid entry if needed for the Sid * passed MutableAcl object. Also will create an acl_sid entry if needed for the Sid
* that owns the MutableAcl. * that owns the MutableAcl.
*
* @param acl to modify (a row must already exist in acl_object_identity) * @param acl to modify (a row must already exist in acl_object_identity)
*
* @throws NotFoundException if the ACL could not be found to update. * @throws NotFoundException if the ACL could not be found to update.
*/ */
protected void updateObjectIdentity(MutableAcl acl) { protected void updateObjectIdentity(MutableAcl acl) {
Long parentId = null; Long parentId = null;
if (acl.getParentAcl() != null) { if (acl.getParentAcl() != null) {
Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl() Assert.isInstanceOf(ObjectIdentityImpl.class, acl.getParentAcl().getObjectIdentity(),
.getObjectIdentity(),
"Implementation only supports ObjectIdentityImpl"); "Implementation only supports ObjectIdentityImpl");
ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl() ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl().getObjectIdentity();
.getObjectIdentity();
parentId = retrieveObjectIdentityPrimaryKey(oii); parentId = retrieveObjectIdentityPrimaryKey(oii);
} }
Assert.notNull(acl.getOwner(), "Owner is required in this implementation"); Assert.notNull(acl.getOwner(), "Owner is required in this implementation");
Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true); Long ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true);
int count = jdbcOperations.update(updateObjectIdentity, parentId, ownerSid, int count = jdbcOperations.update(updateObjectIdentity, parentId, ownerSid, acl.isEntriesInheriting(),
acl.isEntriesInheriting(), acl.getId()); acl.getId());
if (count != 1) { if (count != 1) {
throw new NotFoundException("Unable to locate ACL to update"); throw new NotFoundException("Unable to locate ACL to update");
@ -419,7 +408,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
/** /**
* Sets the query that will be used to retrieve the identity of a newly created row in * Sets the query that will be used to retrieve the identity of a newly created row in
* the <tt>acl_class</tt> table. * the <tt>acl_class</tt> table.
*
* @param classIdentityQuery the query, which should return the identifier. Defaults * @param classIdentityQuery the query, which should return the identifier. Defaults
* to <tt>call identity()</tt> * to <tt>call identity()</tt>
*/ */
@ -431,7 +419,6 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
/** /**
* Sets the query that will be used to retrieve the identity of a newly created row in * Sets the query that will be used to retrieve the identity of a newly created row in
* the <tt>acl_sid</tt> table. * the <tt>acl_sid</tt> table.
*
* @param sidIdentityQuery the query, which should return the identifier. Defaults to * @param sidIdentityQuery the query, which should return the identifier. Defaults to
* <tt>call identity()</tt> * <tt>call identity()</tt>
*/ */
@ -440,13 +427,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
this.sidIdentityQuery = sidIdentityQuery; this.sidIdentityQuery = sidIdentityQuery;
} }
public void setDeleteEntryByObjectIdentityForeignKeySql( public void setDeleteEntryByObjectIdentityForeignKeySql(String deleteEntryByObjectIdentityForeignKey) {
String deleteEntryByObjectIdentityForeignKey) {
this.deleteEntryByObjectIdentityForeignKey = deleteEntryByObjectIdentityForeignKey; this.deleteEntryByObjectIdentityForeignKey = deleteEntryByObjectIdentityForeignKey;
} }
public void setDeleteObjectIdentityByPrimaryKeySql( public void setDeleteObjectIdentityByPrimaryKeySql(String deleteObjectIdentityByPrimaryKey) {
String deleteObjectIdentityByPrimaryKey) {
this.deleteObjectIdentityByPrimaryKey = deleteObjectIdentityByPrimaryKey; this.deleteObjectIdentityByPrimaryKey = deleteObjectIdentityByPrimaryKey;
} }
@ -498,9 +483,11 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
// Change the default insert if it hasn't been overridden // Change the default insert if it hasn't been overridden
if (this.insertClass.equals(DEFAULT_INSERT_INTO_ACL_CLASS)) { if (this.insertClass.equals(DEFAULT_INSERT_INTO_ACL_CLASS)) {
this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID; this.insertClass = DEFAULT_INSERT_INTO_ACL_CLASS_WITH_ID;
} else { }
else {
log.debug("Insert class statement has already been overridden, so not overridding the default"); log.debug("Insert class statement has already been overridden, so not overridding the default");
} }
} }
} }
} }

View File

@ -29,16 +29,15 @@ import java.util.Map;
* @author Ben Alex * @author Ben Alex
*/ */
public interface LookupStrategy { public interface LookupStrategy {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
/** /**
* Perform database-specific optimized lookup. * Perform database-specific optimized lookup.
*
* @param objects the identities to lookup (required) * @param objects the identities to lookup (required)
* @param sids the SIDs for which identities are required (may be <tt>null</tt> - * @param sids the SIDs for which identities are required (may be <tt>null</tt> -
* implementations may elect not to provide SID optimisations) * implementations may elect not to provide SID optimisations)
*
* @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the * @return a <tt>Map</tt> where keys represent the {@link ObjectIdentity} of the
* located {@link Acl} and values are the located {@link Acl} (never <tt>null</tt> * located {@link Acl} and values are the located {@link Acl} (never <tt>null</tt>
* although some entries may be missing; this method should not throw * although some entries may be missing; this method should not throw
@ -46,4 +45,5 @@ public interface LookupStrategy {
* automatically create entries if required) * automatically create entries if required)
*/ */
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids); Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids);
} }

View File

@ -17,4 +17,3 @@
* JDBC-based persistence of ACL information * JDBC-based persistence of ACL information
*/ */
package org.springframework.security.acls.jdbc; package org.springframework.security.acls.jdbc;

View File

@ -29,6 +29,7 @@ import java.io.Serializable;
* *
*/ */
public interface AccessControlEntry extends Serializable { public interface AccessControlEntry extends Serializable {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
@ -36,7 +37,6 @@ public interface AccessControlEntry extends Serializable {
/** /**
* Obtains an identifier that represents this ACE. * Obtains an identifier that represents this ACE.
*
* @return the identifier, or <code>null</code> if unsaved * @return the identifier, or <code>null</code> if unsaved
*/ */
Serializable getId(); Serializable getId();
@ -46,10 +46,10 @@ public interface AccessControlEntry extends Serializable {
Sid getSid(); Sid getSid();
/** /**
* Indicates the permission is being granted to the relevant Sid. If false, * Indicates the permission is being granted to the relevant Sid. If false, indicates
* indicates the permission is being revoked/blocked. * the permission is being revoked/blocked.
*
* @return true if being granted, false otherwise * @return true if being granted, false otherwise
*/ */
boolean isGranting(); boolean isGranting();
} }

View File

@ -63,7 +63,6 @@ public interface Acl extends Serializable {
* subset of <tt>Sid</tt>s. The caller is responsible for correctly handling the * subset of <tt>Sid</tt>s. The caller is responsible for correctly handling the
* result if only a subset of <tt>Sid</tt>s is represented. * result if only a subset of <tt>Sid</tt>s is represented.
* </p> * </p>
*
* @return the list of entries represented by the <tt>Acl</tt>, or <tt>null</tt> if * @return the list of entries represented by the <tt>Acl</tt>, or <tt>null</tt> if
* there are no entries presently associated with this <tt>Acl</tt>. * there are no entries presently associated with this <tt>Acl</tt>.
*/ */
@ -72,7 +71,6 @@ public interface Acl extends Serializable {
/** /**
* Obtains the domain object this <tt>Acl</tt> provides entries for. This is immutable * Obtains the domain object this <tt>Acl</tt> provides entries for. This is immutable
* once an <tt>Acl</tt> is created. * once an <tt>Acl</tt> is created.
*
* @return the object identity (never <tt>null</tt>) * @return the object identity (never <tt>null</tt>)
*/ */
ObjectIdentity getObjectIdentity(); ObjectIdentity getObjectIdentity();
@ -80,7 +78,6 @@ public interface Acl extends Serializable {
/** /**
* Determines the owner of the <tt>Acl</tt>. The meaning of ownership varies by * Determines the owner of the <tt>Acl</tt>. The meaning of ownership varies by
* implementation and is unspecified. * implementation and is unspecified.
*
* @return the owner (may be <tt>null</tt> if the implementation does not use * @return the owner (may be <tt>null</tt> if the implementation does not use
* ownership concepts) * ownership concepts)
*/ */
@ -102,7 +99,6 @@ public interface Acl extends Serializable {
* subset of <tt>Sid</tt>s. The caller is responsible for correctly handling the * subset of <tt>Sid</tt>s. The caller is responsible for correctly handling the
* result if only a subset of <tt>Sid</tt>s is represented. * result if only a subset of <tt>Sid</tt>s is represented.
* </p> * </p>
*
* @return the parent <tt>Acl</tt> (may be <tt>null</tt> if this <tt>Acl</tt> does not * @return the parent <tt>Acl</tt> (may be <tt>null</tt> if this <tt>Acl</tt> does not
* have a parent) * have a parent)
*/ */
@ -118,7 +114,6 @@ public interface Acl extends Serializable {
* parent for navigation purposes. Thus, this method denotes whether or not the * parent for navigation purposes. Thus, this method denotes whether or not the
* navigation relationship also extends to the actual inheritance of entries. * navigation relationship also extends to the actual inheritance of entries.
* </p> * </p>
*
* @return <tt>true</tt> if parent ACL entries inherit into the current <tt>Acl</tt> * @return <tt>true</tt> if parent ACL entries inherit into the current <tt>Acl</tt>
*/ */
boolean isEntriesInheriting(); boolean isEntriesInheriting();
@ -158,7 +153,6 @@ public interface Acl extends Serializable {
* authorization decision for a {@link Sid} that was never loaded in this <tt>Acl</tt> * authorization decision for a {@link Sid} that was never loaded in this <tt>Acl</tt>
* . * .
* </p> * </p>
*
* @param permission the permission or permissions required (at least one entry * @param permission the permission or permissions required (at least one entry
* required) * required)
* @param sids the security identities held by the principal (at least one entry * @param sids the security identities held by the principal (at least one entry
@ -166,17 +160,15 @@ public interface Acl extends Serializable {
* @param administrativeMode if <tt>true</tt> denotes the query is for administrative * @param administrativeMode if <tt>true</tt> denotes the query is for administrative
* purposes and no logging or auditing (if supported by the implementation) should be * purposes and no logging or auditing (if supported by the implementation) should be
* undertaken * undertaken
*
* @return <tt>true</tt> if authorization is granted * @return <tt>true</tt> if authorization is granted
*
* @throws NotFoundException MUST be thrown if an implementation cannot make an * @throws NotFoundException MUST be thrown if an implementation cannot make an
* authoritative authorization decision, usually because there is no ACL information * authoritative authorization decision, usually because there is no ACL information
* for this particular permission and/or SID * for this particular permission and/or SID
* @throws UnloadedSidException thrown if the <tt>Acl</tt> does not have details for * @throws UnloadedSidException thrown if the <tt>Acl</tt> does not have details for
* one or more of the <tt>Sid</tt>s passed as arguments * one or more of the <tt>Sid</tt>s passed as arguments
*/ */
boolean isGranted(List<Permission> permission, List<Sid> sids, boolean isGranted(List<Permission> permission, List<Sid> sids, boolean administrativeMode)
boolean administrativeMode) throws NotFoundException, UnloadedSidException; throws NotFoundException, UnloadedSidException;
/** /**
* For efficiency reasons an <tt>Acl</tt> may be loaded and <em>not</em> contain * For efficiency reasons an <tt>Acl</tt> may be loaded and <em>not</em> contain
@ -191,12 +183,11 @@ public interface Acl extends Serializable {
* all <tt>Sid</tt>s. This method denotes whether or not the specified <tt>Sid</tt>s * all <tt>Sid</tt>s. This method denotes whether or not the specified <tt>Sid</tt>s
* have been loaded or not. * have been loaded or not.
* </p> * </p>
*
* @param sids one or more security identities the caller is interest in knowing * @param sids one or more security identities the caller is interest in knowing
* whether this <tt>Sid</tt> supports * whether this <tt>Sid</tt> supports
*
* @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this * @return <tt>true</tt> if every passed <tt>Sid</tt> is represented by this
* <tt>Acl</tt> instance * <tt>Acl</tt> instance
*/ */
boolean isSidLoaded(List<Sid> sids); boolean isSidLoaded(List<Sid> sids);
} }

View File

@ -26,6 +26,7 @@ import java.io.Serializable;
* *
*/ */
public interface AclCache { public interface AclCache {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
@ -40,4 +41,5 @@ public interface AclCache {
void putInCache(MutableAcl acl); void putInCache(MutableAcl acl);
void clearCache(); void clearCache();
} }

View File

@ -26,7 +26,6 @@ public abstract class AclDataAccessException extends RuntimeException {
/** /**
* Constructs an <code>AclDataAccessException</code> with the specified message and * Constructs an <code>AclDataAccessException</code> with the specified message and
* root cause. * root cause.
*
* @param msg the detail message * @param msg the detail message
* @param cause the root cause * @param cause the root cause
*/ */
@ -37,10 +36,10 @@ public abstract class AclDataAccessException extends RuntimeException {
/** /**
* Constructs an <code>AclDataAccessException</code> with the specified message and no * Constructs an <code>AclDataAccessException</code> with the specified message and no
* root cause. * root cause.
*
* @param msg the detail message * @param msg the detail message
*/ */
public AclDataAccessException(String msg) { public AclDataAccessException(String msg) {
super(msg); super(msg);
} }
} }

View File

@ -24,15 +24,14 @@ import java.util.Map;
* @author Ben Alex * @author Ben Alex
*/ */
public interface AclService { public interface AclService {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
/** /**
* Locates all object identities that use the specified parent. This is useful for * Locates all object identities that use the specified parent. This is useful for
* administration tools. * administration tools.
*
* @param parentIdentity to locate children of * @param parentIdentity to locate children of
*
* @return the children (or <tt>null</tt> if none were found) * @return the children (or <tt>null</tt> if none were found)
*/ */
List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity); List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity);
@ -44,12 +43,9 @@ public interface AclService {
* implementation's potential ability to filter <tt>Acl</tt> entries based on a * implementation's potential ability to filter <tt>Acl</tt> entries based on a
* {@link Sid} parameter. * {@link Sid} parameter.
* </p> * </p>
*
* @param object to locate an {@link Acl} for * @param object to locate an {@link Acl} for
*
* @return the {@link Acl} for the requested {@link ObjectIdentity} (never * @return the {@link Acl} for the requested {@link ObjectIdentity} (never
* <tt>null</tt>) * <tt>null</tt>)
*
* @throws NotFoundException if an {@link Acl} was not found for the requested * @throws NotFoundException if an {@link Acl} was not found for the requested
* {@link ObjectIdentity} * {@link ObjectIdentity}
*/ */
@ -57,14 +53,11 @@ public interface AclService {
/** /**
* Same as {@link #readAclsById(List, List)} except it returns only a single Acl. * Same as {@link #readAclsById(List, List)} except it returns only a single Acl.
*
* @param object to locate an {@link Acl} for * @param object to locate an {@link Acl} for
* @param sids the security identities for which {@link Acl} information is required * @param sids the security identities for which {@link Acl} information is required
* (may be <tt>null</tt> to denote all entries) * (may be <tt>null</tt> to denote all entries)
*
* @return the {@link Acl} for the requested {@link ObjectIdentity} (never * @return the {@link Acl} for the requested {@link ObjectIdentity} (never
* <tt>null</tt>) * <tt>null</tt>)
*
* @throws NotFoundException if an {@link Acl} was not found for the requested * @throws NotFoundException if an {@link Acl} was not found for the requested
* {@link ObjectIdentity} * {@link ObjectIdentity}
*/ */
@ -76,17 +69,13 @@ public interface AclService {
* The returned map is keyed on the passed objects, with the values being the * The returned map is keyed on the passed objects, with the values being the
* <tt>Acl</tt> instances. Any unknown objects will not have a map key. * <tt>Acl</tt> instances. Any unknown objects will not have a map key.
* </p> * </p>
*
* @param objects the objects to find {@link Acl} information for * @param objects the objects to find {@link Acl} information for
*
* @return a map with exactly one element for each {@link ObjectIdentity} passed as an * @return a map with exactly one element for each {@link ObjectIdentity} passed as an
* argument (never <tt>null</tt>) * argument (never <tt>null</tt>)
*
* @throws NotFoundException if an {@link Acl} was not found for each requested * @throws NotFoundException if an {@link Acl} was not found for each requested
* {@link ObjectIdentity} * {@link ObjectIdentity}
*/ */
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException;
throws NotFoundException;
/** /**
* Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s, but only * Obtains all the <tt>Acl</tt>s that apply for the passed <tt>Object</tt>s, but only
@ -103,17 +92,14 @@ public interface AclService {
* <tt>Acl</tt> instances. Any unknown objects (or objects for which the interested * <tt>Acl</tt> instances. Any unknown objects (or objects for which the interested
* <tt>Sid</tt>s do not have entries) will not have a map key. * <tt>Sid</tt>s do not have entries) will not have a map key.
* </p> * </p>
*
* @param objects the objects to find {@link Acl} information for * @param objects the objects to find {@link Acl} information for
* @param sids the security identities for which {@link Acl} information is required * @param sids the security identities for which {@link Acl} information is required
* (may be <tt>null</tt> to denote all entries) * (may be <tt>null</tt> to denote all entries)
*
* @return a map with exactly one element for each {@link ObjectIdentity} passed as an * @return a map with exactly one element for each {@link ObjectIdentity} passed as an
* argument (never <tt>null</tt>) * argument (never <tt>null</tt>)
*
* @throws NotFoundException if an {@link Acl} was not found for each requested * @throws NotFoundException if an {@link Acl} was not found for each requested
* {@link ObjectIdentity} * {@link ObjectIdentity}
*/ */
Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) throws NotFoundException;
throws NotFoundException;
} }

View File

@ -21,12 +21,12 @@ package org.springframework.security.acls.model;
* @author Ben Alex * @author Ben Alex
*/ */
public class AlreadyExistsException extends AclDataAccessException { public class AlreadyExistsException extends AclDataAccessException {
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
/** /**
* Constructs an <code>AlreadyExistsException</code> with the specified message. * Constructs an <code>AlreadyExistsException</code> with the specified message.
*
* @param msg the detail message * @param msg the detail message
*/ */
public AlreadyExistsException(String msg) { public AlreadyExistsException(String msg) {
@ -36,11 +36,11 @@ public class AlreadyExistsException extends AclDataAccessException {
/** /**
* Constructs an <code>AlreadyExistsException</code> with the specified message and * Constructs an <code>AlreadyExistsException</code> with the specified message and
* root cause. * root cause.
*
* @param msg the detail message * @param msg the detail message
* @param t root cause * @param t root cause
*/ */
public AlreadyExistsException(String msg, Throwable t) { public AlreadyExistsException(String msg, Throwable t) {
super(msg, t); super(msg, t);
} }
} }

View File

@ -22,10 +22,12 @@ package org.springframework.security.acls.model;
* *
*/ */
public interface AuditableAccessControlEntry extends AccessControlEntry { public interface AuditableAccessControlEntry extends AccessControlEntry {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
boolean isAuditFailure(); boolean isAuditFailure();
boolean isAuditSuccess(); boolean isAuditSuccess();
} }

View File

@ -22,8 +22,10 @@ package org.springframework.security.acls.model;
* *
*/ */
public interface AuditableAcl extends MutableAcl { public interface AuditableAcl extends MutableAcl {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure); void updateAuditing(int aceIndex, boolean auditSuccess, boolean auditFailure);
} }

View File

@ -21,12 +21,12 @@ package org.springframework.security.acls.model;
* @author Ben Alex * @author Ben Alex
*/ */
public class ChildrenExistException extends AclDataAccessException { public class ChildrenExistException extends AclDataAccessException {
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
/** /**
* Constructs an <code>ChildrenExistException</code> with the specified message. * Constructs an <code>ChildrenExistException</code> with the specified message.
*
* @param msg the detail message * @param msg the detail message
*/ */
public ChildrenExistException(String msg) { public ChildrenExistException(String msg) {
@ -36,11 +36,11 @@ public class ChildrenExistException extends AclDataAccessException {
/** /**
* Constructs an <code>ChildrenExistException</code> with the specified message and * Constructs an <code>ChildrenExistException</code> with the specified message and
* root cause. * root cause.
*
* @param msg the detail message * @param msg the detail message
* @param t root cause * @param t root cause
*/ */
public ChildrenExistException(String msg, Throwable t) { public ChildrenExistException(String msg, Throwable t) {
super(msg, t); super(msg, t);
} }
} }

View File

@ -26,6 +26,7 @@ import java.io.Serializable;
* @author Ben Alex * @author Ben Alex
*/ */
public interface MutableAcl extends Acl { public interface MutableAcl extends Acl {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
@ -33,34 +34,30 @@ public interface MutableAcl extends Acl {
/** /**
* Obtains an identifier that represents this <tt>MutableAcl</tt>. * Obtains an identifier that represents this <tt>MutableAcl</tt>.
*
* @return the identifier, or <tt>null</tt> if unsaved * @return the identifier, or <tt>null</tt> if unsaved
*/ */
Serializable getId(); Serializable getId();
void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) void insertAce(int atIndexLocation, Permission permission, Sid sid, boolean granting) throws NotFoundException;
throws NotFoundException;
/** /**
* Changes the present owner to a different owner. * Changes the present owner to a different owner.
*
* @param newOwner the new owner (mandatory; cannot be null) * @param newOwner the new owner (mandatory; cannot be null)
*/ */
void setOwner(Sid newOwner); void setOwner(Sid newOwner);
/** /**
* Change the value returned by {@link Acl#isEntriesInheriting()}. * Change the value returned by {@link Acl#isEntriesInheriting()}.
*
* @param entriesInheriting the new value * @param entriesInheriting the new value
*/ */
void setEntriesInheriting(boolean entriesInheriting); void setEntriesInheriting(boolean entriesInheriting);
/** /**
* Changes the parent of this ACL. * Changes the parent of this ACL.
*
* @param newParent the new parent * @param newParent the new parent
*/ */
void setParent(Acl newParent); void setParent(Acl newParent);
void updateAce(int aceIndex, Permission permission) throws NotFoundException; void updateAce(int aceIndex, Permission permission) throws NotFoundException;
} }

View File

@ -21,41 +21,35 @@ package org.springframework.security.acls.model;
* @author Ben Alex * @author Ben Alex
*/ */
public interface MutableAclService extends AclService { public interface MutableAclService extends AclService {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
/** /**
* Creates an empty <code>Acl</code> object in the database. It will have no entries. * Creates an empty <code>Acl</code> object in the database. It will have no entries.
* The returned object will then be used to add entries. * The returned object will then be used to add entries.
*
* @param objectIdentity the object identity to create * @param objectIdentity the object identity to create
*
* @return an ACL object with its ID set * @return an ACL object with its ID set
*
* @throws AlreadyExistsException if the passed object identity already has a record * @throws AlreadyExistsException if the passed object identity already has a record
*/ */
MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException; MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException;
/** /**
* Removes the specified entry from the database. * Removes the specified entry from the database.
*
* @param objectIdentity the object identity to remove * @param objectIdentity the object identity to remove
* @param deleteChildren whether to cascade the delete to children * @param deleteChildren whether to cascade the delete to children
*
* @throws ChildrenExistException if the deleteChildren argument was * @throws ChildrenExistException if the deleteChildren argument was
* <code>false</code> but children exist * <code>false</code> but children exist
*/ */
void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException;
throws ChildrenExistException;
/** /**
* Changes an existing <code>Acl</code> in the database. * Changes an existing <code>Acl</code> in the database.
*
* @param acl to modify * @param acl to modify
*
* @throws NotFoundException if the relevant record could not be found (did you * @throws NotFoundException if the relevant record could not be found (did you
* remember to use {@link #createAcl(ObjectIdentity)} to create the object, rather * remember to use {@link #createAcl(ObjectIdentity)} to create the object, rather
* than creating it with the <code>new</code> keyword?) * than creating it with the <code>new</code> keyword?)
*/ */
MutableAcl updateAcl(MutableAcl acl) throws NotFoundException; MutableAcl updateAcl(MutableAcl acl) throws NotFoundException;
} }

View File

@ -21,12 +21,12 @@ package org.springframework.security.acls.model;
* @author Ben Alex * @author Ben Alex
*/ */
public class NotFoundException extends AclDataAccessException { public class NotFoundException extends AclDataAccessException {
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
/** /**
* Constructs an <code>NotFoundException</code> with the specified message. * Constructs an <code>NotFoundException</code> with the specified message.
*
* @param msg the detail message * @param msg the detail message
*/ */
public NotFoundException(String msg) { public NotFoundException(String msg) {
@ -36,11 +36,11 @@ public class NotFoundException extends AclDataAccessException {
/** /**
* Constructs an <code>NotFoundException</code> with the specified message and root * Constructs an <code>NotFoundException</code> with the specified message and root
* cause. * cause.
*
* @param msg the detail message * @param msg the detail message
* @param t root cause * @param t root cause
*/ */
public NotFoundException(String msg, Throwable t) { public NotFoundException(String msg, Throwable t) {
super(msg, t); super(msg, t);
} }
} }

View File

@ -32,12 +32,12 @@ import java.io.Serializable;
* @author Ben Alex * @author Ben Alex
*/ */
public interface ObjectIdentity extends Serializable { public interface ObjectIdentity extends Serializable {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
/** /**
* @param obj to be compared * @param obj to be compared
*
* @return <tt>true</tt> if the objects are equal, <tt>false</tt> otherwise * @return <tt>true</tt> if the objects are equal, <tt>false</tt> otherwise
* @see Object#equals(Object) * @see Object#equals(Object)
*/ */
@ -53,7 +53,6 @@ public interface ObjectIdentity extends Serializable {
* identifier with business meaning, as that business meaning may change in the future * identifier with business meaning, as that business meaning may change in the future
* such change will cascade to the ACL subsystem data. * such change will cascade to the ACL subsystem data.
* </p> * </p>
*
* @return the identifier (unique within this <tt>type</tt>; never <tt>null</tt>) * @return the identifier (unique within this <tt>type</tt>; never <tt>null</tt>)
*/ */
Serializable getIdentifier(); Serializable getIdentifier();
@ -62,7 +61,6 @@ public interface ObjectIdentity extends Serializable {
* Obtains the "type" metadata for the domain object. This will often be a Java type * Obtains the "type" metadata for the domain object. This will often be a Java type
* name (an interface or a class) &ndash; traditionally it is the name of the domain * name (an interface or a class) &ndash; traditionally it is the name of the domain
* object implementation class. * object implementation class.
*
* @return the "type" of the domain object (never <tt>null</tt>). * @return the "type" of the domain object (never <tt>null</tt>).
*/ */
String getType(); String getType();
@ -72,4 +70,5 @@ public interface ObjectIdentity extends Serializable {
* @see Object#hashCode() * @see Object#hashCode()
*/ */
int hashCode(); int hashCode();
} }

View File

@ -30,7 +30,6 @@ import java.io.Serializable;
public interface ObjectIdentityGenerator { public interface ObjectIdentityGenerator {
/** /**
*
* @param id the identifier of the domain object, not null * @param id the identifier of the domain object, not null
* @param type the type of the object (often a class name), not null * @param type the type of the object (often a class name), not null
* @return the identity constructed using the supplied identifier and type * @return the identity constructed using the supplied identifier and type

View File

@ -24,8 +24,10 @@ package org.springframework.security.acls.model;
* *
*/ */
public interface ObjectIdentityRetrievalStrategy { public interface ObjectIdentityRetrievalStrategy {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
ObjectIdentity getObjectIdentity(Object domainObject); ObjectIdentity getObjectIdentity(Object domainObject);
} }

View File

@ -25,8 +25,10 @@ package org.springframework.security.acls.model;
* @author Ben Alex * @author Ben Alex
*/ */
public interface OwnershipAcl extends MutableAcl { public interface OwnershipAcl extends MutableAcl {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
void setOwner(Sid newOwner); void setOwner(Sid newOwner);
} }

View File

@ -23,11 +23,14 @@ import java.io.Serializable;
* @author Ben Alex * @author Ben Alex
*/ */
public interface Permission extends Serializable { public interface Permission extends Serializable {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
char RESERVED_ON = '~'; char RESERVED_ON = '~';
char RESERVED_OFF = '.'; char RESERVED_OFF = '.';
String THIRTY_TWO_RESERVED_OFF = "................................"; String THIRTY_TWO_RESERVED_OFF = "................................";
// ~ Methods // ~ Methods
@ -35,7 +38,6 @@ public interface Permission extends Serializable {
/** /**
* Returns the bits that represents the permission. * Returns the bits that represents the permission.
*
* @return the bits that represent the permission * @return the bits that represent the permission
*/ */
int getMask(); int getMask();
@ -56,8 +58,8 @@ public interface Permission extends Serializable {
* This method is only used for user interface and logging purposes. It is not used in * This method is only used for user interface and logging purposes. It is not used in
* any permission calculations. Therefore, duplication of characters within the output * any permission calculations. Therefore, duplication of characters within the output
* is permitted. * is permitted.
*
* @return a 32-character bit pattern * @return a 32-character bit pattern
*/ */
String getPattern(); String getPattern();
} }

View File

@ -27,10 +27,9 @@ import java.util.List;
public interface PermissionGrantingStrategy { public interface PermissionGrantingStrategy {
/** /**
* Returns true if the supplied strategy decides that the supplied {@code Acl} * Returns true if the supplied strategy decides that the supplied {@code Acl} grants
* grants access based on the supplied list of permissions and sids. * access based on the supplied list of permissions and sids.
*/ */
boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids, boolean isGranted(Acl acl, List<Permission> permission, List<Sid> sids, boolean administrativeMode);
boolean administrativeMode);
} }

View File

@ -31,15 +31,14 @@ import java.io.Serializable;
* @author Ben Alex * @author Ben Alex
*/ */
public interface Sid extends Serializable { public interface Sid extends Serializable {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
/** /**
* Refer to the <code>java.lang.Object</code> documentation for the interface * Refer to the <code>java.lang.Object</code> documentation for the interface
* contract. * contract.
*
* @param obj to be compared * @param obj to be compared
*
* @return <code>true</code> if the objects are equal, <code>false</code> otherwise * @return <code>true</code> if the objects are equal, <code>false</code> otherwise
*/ */
boolean equals(Object obj); boolean equals(Object obj);
@ -47,8 +46,8 @@ public interface Sid extends Serializable {
/** /**
* Refer to the <code>java.lang.Object</code> documentation for the interface * Refer to the <code>java.lang.Object</code> documentation for the interface
* contract. * contract.
*
* @return a hash code representation of this object * @return a hash code representation of this object
*/ */
int hashCode(); int hashCode();
} }

View File

@ -27,8 +27,10 @@ import org.springframework.security.core.Authentication;
* @author Ben Alex * @author Ben Alex
*/ */
public interface SidRetrievalStrategy { public interface SidRetrievalStrategy {
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
List<Sid> getSids(Authentication authentication); List<Sid> getSids(Authentication authentication);
} }

View File

@ -23,12 +23,12 @@ package org.springframework.security.acls.model;
* @author Ben Alex * @author Ben Alex
*/ */
public class UnloadedSidException extends AclDataAccessException { public class UnloadedSidException extends AclDataAccessException {
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
/** /**
* Constructs an <code>NotFoundException</code> with the specified message. * Constructs an <code>NotFoundException</code> with the specified message.
*
* @param msg the detail message * @param msg the detail message
*/ */
public UnloadedSidException(String msg) { public UnloadedSidException(String msg) {
@ -38,11 +38,11 @@ public class UnloadedSidException extends AclDataAccessException {
/** /**
* Constructs an <code>NotFoundException</code> with the specified message and root * Constructs an <code>NotFoundException</code> with the specified message and root
* cause. * cause.
*
* @param msg the detail message * @param msg the detail message
* @param t root cause * @param t root cause
*/ */
public UnloadedSidException(String msg, Throwable t) { public UnloadedSidException(String msg, Throwable t) {
super(msg, t); super(msg, t);
} }
} }

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
/** /**
* Interfaces and shared classes to manage access control lists (ACLs) for domain object instances. * Interfaces and shared classes to manage access control lists (ACLs) for domain object
* instances.
*/ */
package org.springframework.security.acls.model; package org.springframework.security.acls.model;

View File

@ -14,11 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
/** /**
* The Spring Security ACL package which implements instance-based security for domain objects. * The Spring Security ACL package which implements instance-based security for domain
* objects.
* <p> * <p>
* Consider using the annotation based approach ({@code @PreAuthorize}, {@code @PostFilter} annotations) combined * Consider using the annotation based approach ({@code @PreAuthorize},
* with a {@link org.springframework.security.acls.AclPermissionEvaluator} in preference to the older and more verbose * {@code @PostFilter} annotations) combined with a
* attribute/voter/after-invocation approach from versions before Spring Security 3.0. * {@link org.springframework.security.acls.AclPermissionEvaluator} in preference to the
* older and more verbose attribute/voter/after-invocation approach from versions before
* Spring Security 3.0.
*/ */
package org.springframework.security.acls; package org.springframework.security.acls;

View File

@ -66,13 +66,11 @@ public class AclFormattingUtilsTests {
public final void testDemergePatterns() { public final void testDemergePatterns() {
String original = "...........................A...R"; String original = "...........................A...R";
String removeBits = "...............................R"; String removeBits = "...............................R";
assertThat(AclFormattingUtils.demergePatterns(original, removeBits)).isEqualTo( assertThat(AclFormattingUtils.demergePatterns(original, removeBits))
"...........................A...."); .isEqualTo("...........................A....");
assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "......")).isEqualTo( assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "......")).isEqualTo("ABCDEF");
"ABCDEF"); assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "GHIJKL")).isEqualTo("......");
assertThat(AclFormattingUtils.demergePatterns("ABCDEF", "GHIJKL")).isEqualTo(
"......");
} }
@Test @Test
@ -109,19 +107,15 @@ public class AclFormattingUtilsTests {
public final void testMergePatterns() { public final void testMergePatterns() {
String original = "...............................R"; String original = "...............................R";
String extraBits = "...........................A...."; String extraBits = "...........................A....";
assertThat(AclFormattingUtils.mergePatterns(original, extraBits)).isEqualTo( assertThat(AclFormattingUtils.mergePatterns(original, extraBits)).isEqualTo("...........................A...R");
"...........................A...R");
assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "......")).isEqualTo( assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "......")).isEqualTo("ABCDEF");
"ABCDEF"); assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "GHIJKL")).isEqualTo("GHIJKL");
assertThat(AclFormattingUtils.mergePatterns("ABCDEF", "GHIJKL")).isEqualTo(
"GHIJKL");
} }
@Test @Test
public final void testBinaryPrints() { public final void testBinaryPrints() {
assertThat(AclFormattingUtils.printBinary(15)).isEqualTo( assertThat(AclFormattingUtils.printBinary(15)).isEqualTo("............................****");
"............................****");
try { try {
AclFormattingUtils.printBinary(15, Permission.RESERVED_ON); AclFormattingUtils.printBinary(15, Permission.RESERVED_ON);
@ -137,19 +131,17 @@ public class AclFormattingUtilsTests {
catch (IllegalArgumentException notExpected) { catch (IllegalArgumentException notExpected) {
} }
assertThat(AclFormattingUtils.printBinary(15, 'x')).isEqualTo( assertThat(AclFormattingUtils.printBinary(15, 'x')).isEqualTo("............................xxxx");
"............................xxxx");
} }
@Test @Test
public void testPrintBinaryNegative() { public void testPrintBinaryNegative() {
assertThat(AclFormattingUtils.printBinary(0x80000000)).isEqualTo( assertThat(AclFormattingUtils.printBinary(0x80000000)).isEqualTo("*...............................");
"*...............................");
} }
@Test @Test
public void testPrintBinaryMinusOne() { public void testPrintBinaryMinusOne() {
assertThat(AclFormattingUtils.printBinary(0xffffffff)).isEqualTo( assertThat(AclFormattingUtils.printBinary(0xffffffff)).isEqualTo("********************************");
"********************************");
} }
} }

View File

@ -44,8 +44,7 @@ public class AclPermissionCacheOptimizerTests {
pco.setObjectIdentityRetrievalStrategy(oidStrat); pco.setObjectIdentityRetrievalStrategy(oidStrat);
pco.setSidRetrievalStrategy(sidStrat); pco.setSidRetrievalStrategy(sidStrat);
Object[] dos = { new Object(), null, new Object() }; Object[] dos = { new Object(), null, new Object() };
ObjectIdentity[] oids = { new ObjectIdentityImpl("A", "1"), ObjectIdentity[] oids = { new ObjectIdentityImpl("A", "1"), new ObjectIdentityImpl("A", "2") };
new ObjectIdentityImpl("A", "2") };
when(oidStrat.getObjectIdentity(dos[0])).thenReturn(oids[0]); when(oidStrat.getObjectIdentity(dos[0])).thenReturn(oids[0]);
when(oidStrat.getObjectIdentity(dos[2])).thenReturn(oids[1]); when(oidStrat.getObjectIdentity(dos[2])).thenReturn(oids[1]);

View File

@ -30,7 +30,6 @@ import org.springframework.security.acls.model.SidRetrievalStrategy;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
/** /**
*
* @author Luke Taylor * @author Luke Taylor
* @since 3.0 * @since 3.0
*/ */
@ -74,4 +73,5 @@ public class AclPermissionEvaluatorTests {
Locale.setDefault(systemLocale); Locale.setDefault(systemLocale);
} }
} }

View File

@ -33,4 +33,5 @@ public final class TargetObjectWithUUID {
public void setId(UUID id) { public void setId(UUID id) {
this.id = id; this.id = id;
} }
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.springframework.security.acls.afterinvocation; package org.springframework.security.acls.afterinvocation;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@ -36,14 +35,13 @@ import java.util.List;
*/ */
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public class AclEntryAfterInvocationCollectionFilteringProviderTests { public class AclEntryAfterInvocationCollectionFilteringProviderTests {
@Test @Test
public void objectsAreRemovedIfPermissionDenied() { public void objectsAreRemovedIfPermissionDenied() {
AclService service = mock(AclService.class); AclService service = mock(AclService.class);
Acl acl = mock(Acl.class); Acl acl = mock(Acl.class);
when(acl.isGranted(any(), any(), anyBoolean())).thenReturn( when(acl.isGranted(any(), any(), anyBoolean())).thenReturn(false);
false); when(service.readAclById(any(), any())).thenReturn(acl);
when(service.readAclById(any(), any())).thenReturn(
acl);
AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider( AclEntryAfterInvocationCollectionFilteringProvider provider = new AclEntryAfterInvocationCollectionFilteringProvider(
service, Arrays.asList(mock(Permission.class))); service, Arrays.asList(mock(Permission.class)));
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
@ -51,8 +49,8 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests {
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
Object returned = provider.decide(mock(Authentication.class), new Object(), Object returned = provider.decide(mock(Authentication.class), new Object(),
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), new ArrayList( SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"),
Arrays.asList(new Object(), new Object()))); new ArrayList(Arrays.asList(new Object(), new Object())));
assertThat(returned).isInstanceOf(List.class); assertThat(returned).isInstanceOf(List.class);
assertThat(((List) returned)).isEmpty(); assertThat(((List) returned)).isEmpty();
returned = provider.decide(mock(Authentication.class), new Object(), returned = provider.decide(mock(Authentication.class), new Object(),
@ -68,10 +66,8 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests {
mock(AclService.class), Arrays.asList(mock(Permission.class))); mock(AclService.class), Arrays.asList(mock(Permission.class)));
Object returned = new Object(); Object returned = new Object();
assertThat(returned) assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(),
.isSameAs( Collections.<ConfigAttribute>emptyList(), returned));
provider.decide(mock(Authentication.class), new Object(),
Collections.<ConfigAttribute> emptyList(), returned));
} }
@Test @Test
@ -81,8 +77,7 @@ public class AclEntryAfterInvocationCollectionFilteringProviderTests {
service, Arrays.asList(mock(Permission.class))); service, Arrays.asList(mock(Permission.class)));
assertThat(provider.decide(mock(Authentication.class), new Object(), assertThat(provider.decide(mock(Authentication.class), new Object(),
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)) SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)).isNull();
.isNull();
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class)); verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
} }

View File

@ -44,74 +44,59 @@ public class AclEntryAfterInvocationProviderTests {
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
} }
new AclEntryAfterInvocationProvider(mock(AclService.class), new AclEntryAfterInvocationProvider(mock(AclService.class), Collections.<Permission>emptyList());
Collections.<Permission> emptyList());
} }
@Test @Test
public void accessIsAllowedIfPermissionIsGranted() { public void accessIsAllowedIfPermissionIsGranted() {
AclService service = mock(AclService.class); AclService service = mock(AclService.class);
Acl acl = mock(Acl.class); Acl acl = mock(Acl.class);
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn( when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(true);
true); when(service.readAclById(any(), any())).thenReturn(acl);
when(service.readAclById(any(), any())).thenReturn( AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service,
acl); Arrays.asList(mock(Permission.class)));
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(
service, Arrays.asList(mock(Permission.class)));
provider.setMessageSource(new SpringSecurityMessageSource()); provider.setMessageSource(new SpringSecurityMessageSource());
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
provider.setProcessDomainObjectClass(Object.class); provider.setProcessDomainObjectClass(Object.class);
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
Object returned = new Object(); Object returned = new Object();
assertThat( assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(),
returned) SecurityConfig.createList("AFTER_ACL_READ"), returned));
.isSameAs(
provider.decide(mock(Authentication.class), new Object(),
SecurityConfig.createList("AFTER_ACL_READ"), returned));
} }
@Test @Test
public void accessIsGrantedIfNoAttributesDefined() { public void accessIsGrantedIfNoAttributesDefined() {
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class),
mock(AclService.class), Arrays.asList(mock(Permission.class))); Arrays.asList(mock(Permission.class)));
Object returned = new Object(); Object returned = new Object();
assertThat( assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(),
returned) Collections.<ConfigAttribute>emptyList(), returned));
.isSameAs(
provider.decide(mock(Authentication.class), new Object(),
Collections.<ConfigAttribute> emptyList(), returned));
} }
@Test @Test
public void accessIsGrantedIfObjectTypeNotSupported() { public void accessIsGrantedIfObjectTypeNotSupported() {
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(mock(AclService.class),
mock(AclService.class), Arrays.asList(mock(Permission.class))); Arrays.asList(mock(Permission.class)));
provider.setProcessDomainObjectClass(String.class); provider.setProcessDomainObjectClass(String.class);
// Not a String // Not a String
Object returned = new Object(); Object returned = new Object();
assertThat( assertThat(returned).isSameAs(provider.decide(mock(Authentication.class), new Object(),
returned) SecurityConfig.createList("AFTER_ACL_READ"), returned));
.isSameAs(
provider.decide(mock(Authentication.class), new Object(),
SecurityConfig.createList("AFTER_ACL_READ"), returned));
} }
@Test(expected = AccessDeniedException.class) @Test(expected = AccessDeniedException.class)
public void accessIsDeniedIfPermissionIsNotGranted() { public void accessIsDeniedIfPermissionIsNotGranted() {
AclService service = mock(AclService.class); AclService service = mock(AclService.class);
Acl acl = mock(Acl.class); Acl acl = mock(Acl.class);
when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn( when(acl.isGranted(any(List.class), any(List.class), anyBoolean())).thenReturn(false);
false);
// Try a second time with no permissions found // Try a second time with no permissions found
when(acl.isGranted(any(), any(List.class), anyBoolean())).thenThrow( when(acl.isGranted(any(), any(List.class), anyBoolean())).thenThrow(new NotFoundException(""));
new NotFoundException("")); when(service.readAclById(any(), any())).thenReturn(acl);
when(service.readAclById(any(), any())).thenReturn( AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service,
acl); Arrays.asList(mock(Permission.class)));
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(
service, Arrays.asList(mock(Permission.class)));
provider.setProcessConfigAttribute("MY_ATTRIBUTE"); provider.setProcessConfigAttribute("MY_ATTRIBUTE");
provider.setMessageSource(new SpringSecurityMessageSource()); provider.setMessageSource(new SpringSecurityMessageSource());
provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class)); provider.setObjectIdentityRetrievalStrategy(mock(ObjectIdentityRetrievalStrategy.class));
@ -119,8 +104,7 @@ public class AclEntryAfterInvocationProviderTests {
provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class)); provider.setSidRetrievalStrategy(mock(SidRetrievalStrategy.class));
try { try {
provider.decide(mock(Authentication.class), new Object(), provider.decide(mock(Authentication.class), new Object(),
SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), SecurityConfig.createList("UNSUPPORTED", "MY_ATTRIBUTE"), new Object());
new Object());
fail("Expected Exception"); fail("Expected Exception");
} }
catch (AccessDeniedException expected) { catch (AccessDeniedException expected) {
@ -133,12 +117,12 @@ public class AclEntryAfterInvocationProviderTests {
@Test @Test
public void nullReturnObjectIsIgnored() { public void nullReturnObjectIsIgnored() {
AclService service = mock(AclService.class); AclService service = mock(AclService.class);
AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider( AclEntryAfterInvocationProvider provider = new AclEntryAfterInvocationProvider(service,
service, Arrays.asList(mock(Permission.class))); Arrays.asList(mock(Permission.class)));
assertThat(provider.decide(mock(Authentication.class), new Object(), assertThat(provider.decide(mock(Authentication.class), new Object(),
SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)) SecurityConfig.createList("AFTER_ACL_COLLECTION_READ"), null)).isNull();
.isNull();
verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class)); verify(service, never()).readAclById(any(ObjectIdentity.class), any(List.class));
} }
} }

View File

@ -39,8 +39,8 @@ public class AccessControlImplEntryTests {
public void testConstructorRequiredFields() { public void testConstructorRequiredFields() {
// Check Acl field is present // Check Acl field is present
try { try {
new AccessControlEntryImpl(null, null, new PrincipalSid("johndoe"), new AccessControlEntryImpl(null, null, new PrincipalSid("johndoe"), BasePermission.ADMINISTRATION, true,
BasePermission.ADMINISTRATION, true, true, true); true, true);
fail("It should have thrown IllegalArgumentException"); fail("It should have thrown IllegalArgumentException");
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
@ -48,8 +48,7 @@ public class AccessControlImplEntryTests {
// Check Sid field is present // Check Sid field is present
try { try {
new AccessControlEntryImpl(null, mock(Acl.class), null, new AccessControlEntryImpl(null, mock(Acl.class), null, BasePermission.ADMINISTRATION, true, true, true);
BasePermission.ADMINISTRATION, true, true, true);
fail("It should have thrown IllegalArgumentException"); fail("It should have thrown IllegalArgumentException");
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
@ -57,8 +56,7 @@ public class AccessControlImplEntryTests {
// Check Permission field is present // Check Permission field is present
try { try {
new AccessControlEntryImpl(null, mock(Acl.class), new AccessControlEntryImpl(null, mock(Acl.class), new PrincipalSid("johndoe"), null, true, true, true);
new PrincipalSid("johndoe"), null, true, true, true);
fail("It should have thrown IllegalArgumentException"); fail("It should have thrown IllegalArgumentException");
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
@ -71,8 +69,8 @@ public class AccessControlImplEntryTests {
Sid sid = new PrincipalSid("johndoe"); Sid sid = new PrincipalSid("johndoe");
// Create a sample entry // Create a sample entry
AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true,
sid, BasePermission.ADMINISTRATION, true, true, true); true);
// and check every get() method // and check every get() method
assertThat(ace.getId()).isEqualTo(1L); assertThat(ace.getId()).isEqualTo(1L);
@ -92,26 +90,26 @@ public class AccessControlImplEntryTests {
when(mockAcl.getObjectIdentity()).thenReturn(oid); when(mockAcl.getObjectIdentity()).thenReturn(oid);
Sid sid = new PrincipalSid("johndoe"); Sid sid = new PrincipalSid("johndoe");
AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, AccessControlEntry ace = new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true,
sid, BasePermission.ADMINISTRATION, true, true, true); true);
assertThat(ace).isNotNull(); assertThat(ace).isNotNull();
assertThat(ace).isNotEqualTo(100L); assertThat(ace).isNotEqualTo(100L);
assertThat(ace).isEqualTo(ace); assertThat(ace).isEqualTo(ace);
assertThat(ace).isEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, assertThat(ace).isEqualTo(
new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, true));
assertThat(ace).isNotEqualTo(
new AccessControlEntryImpl(2L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, true));
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, new PrincipalSid("scott"),
BasePermission.ADMINISTRATION, true, true, true)); BasePermission.ADMINISTRATION, true, true, true));
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(2L, mockAcl, sid, assertThat(ace)
BasePermission.ADMINISTRATION, true, true, true)); .isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.WRITE, true, true, true));
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, assertThat(ace).isNotEqualTo(
new PrincipalSid("scott"), BasePermission.ADMINISTRATION, true, true, new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, false, true, true));
true)); assertThat(ace).isNotEqualTo(
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, false, true));
BasePermission.WRITE, true, true, true)); assertThat(ace).isNotEqualTo(
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid, new AccessControlEntryImpl(1L, mockAcl, sid, BasePermission.ADMINISTRATION, true, true, false));
BasePermission.ADMINISTRATION, false, true, true));
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid,
BasePermission.ADMINISTRATION, true, false, true));
assertThat(ace).isNotEqualTo(new AccessControlEntryImpl(1L, mockAcl, sid,
BasePermission.ADMINISTRATION, true, true, false));
} }
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.springframework.security.acls.domain; package org.springframework.security.acls.domain;
import java.util.Arrays; import java.util.Arrays;
import org.junit.After; import org.junit.After;
@ -31,21 +30,24 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
/** /**
*
* @author Rob Winch * @author Rob Winch
* *
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class AclAuthorizationStrategyImplTests { public class AclAuthorizationStrategyImplTests {
@Mock @Mock
Acl acl; Acl acl;
GrantedAuthority authority; GrantedAuthority authority;
AclAuthorizationStrategyImpl strategy; AclAuthorizationStrategyImpl strategy;
@Before @Before
public void setup() { public void setup() {
authority = new SimpleGrantedAuthority("ROLE_AUTH"); authority = new SimpleGrantedAuthority("ROLE_AUTH");
TestingAuthenticationToken authentication = new TestingAuthenticationToken("foo", "bar", Arrays.asList(authority)); TestingAuthenticationToken authentication = new TestingAuthenticationToken("foo", "bar",
Arrays.asList(authority));
authentication.setAuthenticated(true); authentication.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(authentication); SecurityContextHolder.getContext().setAuthentication(authentication);
} }
@ -64,9 +66,12 @@ public class AclAuthorizationStrategyImplTests {
@SuppressWarnings("serial") @SuppressWarnings("serial")
class CustomAuthority implements GrantedAuthority { class CustomAuthority implements GrantedAuthority {
@Override @Override
public String getAuthority() { public String getAuthority() {
return authority.getAuthority(); return authority.getAuthority();
} }
} }
} }

View File

@ -35,20 +35,31 @@ import java.util.*;
* @author Andrei Stefan * @author Andrei Stefan
*/ */
public class AclImplTests { public class AclImplTests {
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
private static final List<Permission> READ = Arrays.asList(BasePermission.READ); private static final List<Permission> READ = Arrays.asList(BasePermission.READ);
private static final List<Permission> WRITE = Arrays.asList(BasePermission.WRITE); private static final List<Permission> WRITE = Arrays.asList(BasePermission.WRITE);
private static final List<Permission> CREATE = Arrays.asList(BasePermission.CREATE); private static final List<Permission> CREATE = Arrays.asList(BasePermission.CREATE);
private static final List<Permission> DELETE = Arrays.asList(BasePermission.DELETE); private static final List<Permission> DELETE = Arrays.asList(BasePermission.DELETE);
private static final List<Sid> SCOTT = Arrays.asList((Sid) new PrincipalSid("scott")); private static final List<Sid> SCOTT = Arrays.asList((Sid) new PrincipalSid("scott"));
private static final List<Sid> BEN = Arrays.asList((Sid) new PrincipalSid("ben")); private static final List<Sid> BEN = Arrays.asList((Sid) new PrincipalSid("ben"));
Authentication auth = new TestingAuthenticationToken("joe", "ignored", Authentication auth = new TestingAuthenticationToken("joe", "ignored", "ROLE_ADMINISTRATOR");
"ROLE_ADMINISTRATOR");
AclAuthorizationStrategy authzStrategy; AclAuthorizationStrategy authzStrategy;
PermissionGrantingStrategy pgs; PermissionGrantingStrategy pgs;
AuditLogger mockAuditLogger; AuditLogger mockAuditLogger;
ObjectIdentity objectIdentity = new ObjectIdentityImpl(TARGET_CLASS, 100); ObjectIdentity objectIdentity = new ObjectIdentityImpl(TARGET_CLASS, 100);
private DefaultPermissionFactory permissionFactory; private DefaultPermissionFactory permissionFactory;
// ~ Methods // ~ Methods
@ -72,8 +83,7 @@ public class AclImplTests {
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
public void constructorsRejectNullObjectIdentity() { public void constructorsRejectNullObjectIdentity() {
try { try {
new AclImpl(null, 1, authzStrategy, pgs, null, null, true, new PrincipalSid( new AclImpl(null, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
"joe"));
fail("Should have thrown IllegalArgumentException"); fail("Should have thrown IllegalArgumentException");
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
@ -84,8 +94,7 @@ public class AclImplTests {
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
public void constructorsRejectNullId() { public void constructorsRejectNullId() {
try { try {
new AclImpl(objectIdentity, null, authzStrategy, pgs, null, null, true, new AclImpl(objectIdentity, null, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
new PrincipalSid("joe"));
fail("Should have thrown IllegalArgumentException"); fail("Should have thrown IllegalArgumentException");
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
@ -97,8 +106,8 @@ public class AclImplTests {
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
public void constructorsRejectNullAclAuthzStrategy() { public void constructorsRejectNullAclAuthzStrategy() {
try { try {
new AclImpl(objectIdentity, 1, null, new DefaultPermissionGrantingStrategy( new AclImpl(objectIdentity, 1, null, new DefaultPermissionGrantingStrategy(mockAuditLogger), null, null,
mockAuditLogger), null, null, true, new PrincipalSid("joe")); true, new PrincipalSid("joe"));
fail("It should have thrown IllegalArgumentException"); fail("It should have thrown IllegalArgumentException");
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
@ -108,8 +117,7 @@ public class AclImplTests {
@Test @Test
public void insertAceRejectsNullParameters() { public void insertAceRejectsNullParameters() {
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
try { try {
acl.insertAce(0, null, new GrantedAuthoritySid("ROLE_IGNORED"), true); acl.insertAce(0, null, new GrantedAuthoritySid("ROLE_IGNORED"), true);
fail("It should have thrown IllegalArgumentException"); fail("It should have thrown IllegalArgumentException");
@ -126,8 +134,7 @@ public class AclImplTests {
@Test @Test
public void insertAceAddsElementAtCorrectIndex() { public void insertAceAddsElementAtCorrectIndex() {
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
MockAclService service = new MockAclService(); MockAclService service = new MockAclService();
// Insert one permission // Insert one permission
@ -137,8 +144,7 @@ public class AclImplTests {
assertThat(acl.getEntries()).hasSize(1); assertThat(acl.getEntries()).hasSize(1);
assertThat(acl).isEqualTo(acl.getEntries().get(0).getAcl()); assertThat(acl).isEqualTo(acl.getEntries().get(0).getAcl());
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission()); assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission());
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid( assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST1"));
"ROLE_TEST1"));
// Add a second permission // Add a second permission
acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true); acl.insertAce(1, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true);
@ -147,44 +153,36 @@ public class AclImplTests {
assertThat(acl.getEntries()).hasSize(2); assertThat(acl.getEntries()).hasSize(2);
assertThat(acl).isEqualTo(acl.getEntries().get(1).getAcl()); assertThat(acl).isEqualTo(acl.getEntries().get(1).getAcl());
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(1).getPermission()); assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(1).getPermission());
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid( assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2"));
"ROLE_TEST2"));
// Add a third permission, after the first one // Add a third permission, after the first one
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"), acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_TEST3"), false);
false);
service.updateAcl(acl); service.updateAcl(acl);
assertThat(acl.getEntries()).hasSize(3); assertThat(acl.getEntries()).hasSize(3);
// Check the third entry was added between the two existent ones // Check the third entry was added between the two existent ones
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission()); assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(0).getPermission());
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid( assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST1"));
"ROLE_TEST1"));
assertThat(BasePermission.WRITE).isEqualTo(acl.getEntries().get(1).getPermission()); assertThat(BasePermission.WRITE).isEqualTo(acl.getEntries().get(1).getPermission());
assertThat(acl.getEntries().get(1).getSid()).isEqualTo( new GrantedAuthoritySid( assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST3"));
"ROLE_TEST3"));
assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(2).getPermission()); assertThat(BasePermission.READ).isEqualTo(acl.getEntries().get(2).getPermission());
assertThat(acl.getEntries().get(2).getSid()).isEqualTo(new GrantedAuthoritySid( assertThat(acl.getEntries().get(2).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2"));
"ROLE_TEST2"));
} }
@Test(expected = NotFoundException.class) @Test(expected = NotFoundException.class)
public void insertAceFailsForNonExistentElement() { public void insertAceFailsForNonExistentElement() {
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
MockAclService service = new MockAclService(); MockAclService service = new MockAclService();
// Insert one permission // Insert one permission
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true); acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST1"), true);
service.updateAcl(acl); service.updateAcl(acl);
acl.insertAce(55, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), acl.insertAce(55, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST2"), true);
true);
} }
@Test @Test
public void deleteAceKeepsInitialOrdering() { public void deleteAceKeepsInitialOrdering() {
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
MockAclService service = new MockAclService(); MockAclService service = new MockAclService();
// Add several permissions // Add several permissions
@ -197,20 +195,16 @@ public class AclImplTests {
// kept // kept
acl.deleteAce(0); acl.deleteAce(0);
assertThat(acl.getEntries()).hasSize(2); assertThat(acl.getEntries()).hasSize(2);
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid( assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2"));
"ROLE_TEST2")); assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST3"));
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid(
"ROLE_TEST3"));
// Add one more permission and remove the permission in the middle // Add one more permission and remove the permission in the middle
acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST4"), true); acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_TEST4"), true);
service.updateAcl(acl); service.updateAcl(acl);
acl.deleteAce(1); acl.deleteAce(1);
assertThat(acl.getEntries()).hasSize(2); assertThat(acl.getEntries()).hasSize(2);
assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid( assertThat(acl.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST2"));
"ROLE_TEST2")); assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST4"));
assertThat(acl.getEntries().get(1).getSid()).isEqualTo(new GrantedAuthoritySid(
"ROLE_TEST4"));
// Remove remaining permissions // Remove remaining permissions
acl.deleteAce(1); acl.deleteAce(1);
@ -221,10 +215,9 @@ public class AclImplTests {
@Test @Test
public void deleteAceFailsForNonExistentElement() { public void deleteAceFailsForNonExistentElement() {
AclAuthorizationStrategyImpl strategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategyImpl strategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); new SimpleGrantedAuthority("ROLE_GENERAL"));
MutableAcl acl = new AclImpl(objectIdentity, (1), strategy, pgs, null, null, MutableAcl acl = new AclImpl(objectIdentity, (1), strategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
try { try {
acl.deleteAce(99); acl.deleteAce(99);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
@ -235,8 +228,7 @@ public class AclImplTests {
@Test @Test
public void isGrantingRejectsEmptyParameters() { public void isGrantingRejectsEmptyParameters() {
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
Sid ben = new PrincipalSid("ben"); Sid ben = new PrincipalSid("ben");
try { try {
acl.isGranted(new ArrayList<>(0), Arrays.asList(ben), false); acl.isGranted(new ArrayList<>(0), Arrays.asList(ben), false);
@ -254,28 +246,23 @@ public class AclImplTests {
@Test @Test
public void isGrantingGrantsAccessForAclWithNoParent() { public void isGrantingGrantsAccessForAclWithNoParent() {
Authentication auth = new TestingAuthenticationToken("ben", "ignored", Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL", "ROLE_GUEST");
"ROLE_GENERAL", "ROLE_GUEST");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity rootOid = new ObjectIdentityImpl(TARGET_CLASS, 100); ObjectIdentity rootOid = new ObjectIdentityImpl(TARGET_CLASS, 100);
// Create an ACL which owner is not the authenticated principal // Create an ACL which owner is not the authenticated principal
MutableAcl rootAcl = new AclImpl(rootOid, 1, authzStrategy, pgs, null, null, MutableAcl rootAcl = new AclImpl(rootOid, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe"));
false, new PrincipalSid("joe"));
// Grant some permissions // Grant some permissions
rootAcl.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), false); rootAcl.insertAce(0, BasePermission.READ, new PrincipalSid("ben"), false);
rootAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("scott"), true); rootAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("scott"), true);
rootAcl.insertAce(2, BasePermission.WRITE, new PrincipalSid("rod"), false); rootAcl.insertAce(2, BasePermission.WRITE, new PrincipalSid("rod"), false);
rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid( rootAcl.insertAce(3, BasePermission.WRITE, new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), true);
"WRITE_ACCESS_ROLE"), true);
// Check permissions granting // Check permissions granting
List<Permission> permissions = Arrays.asList(BasePermission.READ, List<Permission> permissions = Arrays.asList(BasePermission.READ, BasePermission.CREATE);
BasePermission.CREATE); List<Sid> sids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_GUEST"));
List<Sid> sids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid(
"ROLE_GUEST"));
assertThat(rootAcl.isGranted(permissions, sids, false)).isFalse(); assertThat(rootAcl.isGranted(permissions, sids, false)).isFalse();
try { try {
rootAcl.isGranted(permissions, SCOTT, false); rootAcl.isGranted(permissions, SCOTT, false);
@ -284,14 +271,14 @@ public class AclImplTests {
catch (NotFoundException expected) { catch (NotFoundException expected) {
} }
assertThat(rootAcl.isGranted(WRITE, SCOTT, false)).isTrue(); assertThat(rootAcl.isGranted(WRITE, SCOTT, false)).isTrue();
assertThat(rootAcl.isGranted(WRITE, Arrays.asList(new PrincipalSid("rod"), assertThat(rootAcl.isGranted(WRITE,
new GrantedAuthoritySid("WRITE_ACCESS_ROLE")), false)).isFalse(); Arrays.asList(new PrincipalSid("rod"), new GrantedAuthoritySid("WRITE_ACCESS_ROLE")), false)).isFalse();
assertThat(rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid( assertThat(rootAcl.isGranted(WRITE,
"WRITE_ACCESS_ROLE"), new PrincipalSid("rod")), false)).isTrue(); Arrays.asList(new GrantedAuthoritySid("WRITE_ACCESS_ROLE"), new PrincipalSid("rod")), false)).isTrue();
try { try {
// Change the type of the Sid and check the granting process // Change the type of the Sid and check the granting process
rootAcl.isGranted(WRITE, Arrays.asList(new GrantedAuthoritySid("rod"), rootAcl.isGranted(WRITE,
new PrincipalSid("WRITE_ACCESS_ROLE")), false); Arrays.asList(new GrantedAuthoritySid("rod"), new PrincipalSid("WRITE_ACCESS_ROLE")), false);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -300,8 +287,7 @@ public class AclImplTests {
@Test @Test
public void isGrantingGrantsAccessForInheritableAcls() { public void isGrantingGrantsAccessForInheritableAcls() {
Authentication auth = new TestingAuthenticationToken("ben", "ignored", Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL");
"ROLE_GENERAL");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100); ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100);
@ -312,16 +298,11 @@ public class AclImplTests {
// Create ACLs // Create ACLs
PrincipalSid joe = new PrincipalSid("joe"); PrincipalSid joe = new PrincipalSid("joe");
MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, authzStrategy, pgs, MutableAcl grandParentAcl = new AclImpl(grandParentOid, 1, authzStrategy, pgs, null, null, false, joe);
null, null, false, joe); MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, authzStrategy, pgs, null, null, true, joe);
MutableAcl parentAcl1 = new AclImpl(parentOid1, 2, authzStrategy, pgs, null, MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, authzStrategy, pgs, null, null, true, joe);
null, true, joe); MutableAcl childAcl1 = new AclImpl(childOid1, 4, authzStrategy, pgs, null, null, true, joe);
MutableAcl parentAcl2 = new AclImpl(parentOid2, 3, authzStrategy, pgs, null, MutableAcl childAcl2 = new AclImpl(childOid2, 4, authzStrategy, pgs, null, null, false, joe);
null, true, joe);
MutableAcl childAcl1 = new AclImpl(childOid1, 4, authzStrategy, pgs, null, null,
true, joe);
MutableAcl childAcl2 = new AclImpl(childOid2, 4, authzStrategy, pgs, null, null,
false, joe);
// Create hierarchies // Create hierarchies
childAcl2.setParent(childAcl1); childAcl2.setParent(childAcl1);
@ -330,13 +311,10 @@ public class AclImplTests {
parentAcl1.setParent(grandParentAcl); parentAcl1.setParent(grandParentAcl);
// Add some permissions // Add some permissions
grandParentAcl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid( grandParentAcl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
"ROLE_USER_READ"), true);
grandParentAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("ben"), true); grandParentAcl.insertAce(1, BasePermission.WRITE, new PrincipalSid("ben"), true);
grandParentAcl grandParentAcl.insertAce(2, BasePermission.DELETE, new PrincipalSid("ben"), false);
.insertAce(2, BasePermission.DELETE, new PrincipalSid("ben"), false); grandParentAcl.insertAce(3, BasePermission.DELETE, new PrincipalSid("scott"), true);
grandParentAcl.insertAce(3, BasePermission.DELETE, new PrincipalSid("scott"),
true);
parentAcl1.insertAce(0, BasePermission.READ, new PrincipalSid("scott"), true); parentAcl1.insertAce(0, BasePermission.READ, new PrincipalSid("scott"), true);
parentAcl1.insertAce(1, BasePermission.DELETE, new PrincipalSid("scott"), false); parentAcl1.insertAce(1, BasePermission.DELETE, new PrincipalSid("scott"), false);
parentAcl2.insertAce(0, BasePermission.CREATE, new PrincipalSid("ben"), true); parentAcl2.insertAce(0, BasePermission.CREATE, new PrincipalSid("ben"), true);
@ -344,8 +322,7 @@ public class AclImplTests {
// Check granting process for parent1 // Check granting process for parent1
assertThat(parentAcl1.isGranted(READ, SCOTT, false)).isTrue(); assertThat(parentAcl1.isGranted(READ, SCOTT, false)).isTrue();
assertThat(parentAcl1.isGranted(READ, assertThat(parentAcl1.isGranted(READ, Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false))
Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false))
.isTrue(); .isTrue();
assertThat(parentAcl1.isGranted(WRITE, BEN, false)).isTrue(); assertThat(parentAcl1.isGranted(WRITE, BEN, false)).isTrue();
assertThat(parentAcl1.isGranted(DELETE, BEN, false)).isFalse(); assertThat(parentAcl1.isGranted(DELETE, BEN, false)).isFalse();
@ -358,8 +335,7 @@ public class AclImplTests {
// Check granting process for child1 // Check granting process for child1
assertThat(childAcl1.isGranted(CREATE, SCOTT, false)).isTrue(); assertThat(childAcl1.isGranted(CREATE, SCOTT, false)).isTrue();
assertThat(childAcl1.isGranted(READ, assertThat(childAcl1.isGranted(READ, Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false))
Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_USER_READ")), false))
.isTrue(); .isTrue();
assertThat(childAcl1.isGranted(DELETE, BEN, false)).isFalse(); assertThat(childAcl1.isGranted(DELETE, BEN, false)).isFalse();
@ -372,8 +348,7 @@ public class AclImplTests {
catch (NotFoundException expected) { catch (NotFoundException expected) {
} }
try { try {
childAcl2.isGranted(CREATE, childAcl2.isGranted(CREATE, Arrays.asList((Sid) new PrincipalSid("joe")), false);
Arrays.asList((Sid) new PrincipalSid("joe")), false);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -382,18 +357,14 @@ public class AclImplTests {
@Test @Test
public void updatedAceValuesAreCorrectlyReflectedInAcl() { public void updatedAceValuesAreCorrectlyReflectedInAcl() {
Authentication auth = new TestingAuthenticationToken("ben", "ignored", Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL");
"ROLE_GENERAL");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe"));
false, new PrincipalSid("joe"));
MockAclService service = new MockAclService(); MockAclService service = new MockAclService();
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
true); acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true);
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"),
true);
acl.insertAce(2, BasePermission.CREATE, new PrincipalSid("ben"), true); acl.insertAce(2, BasePermission.CREATE, new PrincipalSid("ben"), true);
service.updateAcl(acl); service.updateAcl(acl);
@ -414,32 +385,20 @@ public class AclImplTests {
@Test @Test
public void auditableEntryFlagsAreUpdatedCorrectly() { public void auditableEntryFlagsAreUpdatedCorrectly() {
Authentication auth = new TestingAuthenticationToken("ben", "ignored", Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_AUDITING", "ROLE_GENERAL");
"ROLE_AUDITING", "ROLE_GENERAL");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, false, new PrincipalSid("joe"));
false, new PrincipalSid("joe"));
MockAclService service = new MockAclService(); MockAclService service = new MockAclService();
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
true); acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true);
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"),
true);
service.updateAcl(acl); service.updateAcl(acl);
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0)) assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditFailure()).isFalse();
.isAuditFailure()) assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditFailure()).isFalse();
.isFalse(); assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0)).isAuditSuccess()).isFalse();
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1)) assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1)).isAuditSuccess()).isFalse();
.isAuditFailure())
.isFalse();
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(0))
.isAuditSuccess())
.isFalse();
assertThat(((AuditableAccessControlEntry) acl.getEntries().get(1))
.isAuditSuccess())
.isFalse();
// Change each permission // Change each permission
((AuditableAcl) acl).updateAuditing(0, true, true); ((AuditableAcl) acl).updateAuditing(0, true, true);
@ -452,21 +411,16 @@ public class AclImplTests {
@Test @Test
public void gettersAndSettersAreConsistent() { public void gettersAndSettersAreConsistent() {
Authentication auth = new TestingAuthenticationToken("ben", "ignored", Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_GENERAL");
"ROLE_GENERAL");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, (100)); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, (100));
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, (101)); ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, (101));
MutableAcl acl = new AclImpl(identity, 1, authzStrategy, pgs, null, null, true, MutableAcl acl = new AclImpl(identity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
new PrincipalSid("joe")); MutableAcl parentAcl = new AclImpl(identity2, 2, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
MutableAcl parentAcl = new AclImpl(identity2, 2, authzStrategy, pgs, null, null,
true, new PrincipalSid("joe"));
MockAclService service = new MockAclService(); MockAclService service = new MockAclService();
acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), acl.insertAce(0, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER_READ"), true);
true); acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"), true);
acl.insertAce(1, BasePermission.WRITE, new GrantedAuthoritySid("ROLE_USER_READ"),
true);
service.updateAcl(acl); service.updateAcl(acl);
assertThat(1).isEqualTo(acl.getId()); assertThat(1).isEqualTo(acl.getId());
@ -488,50 +442,43 @@ public class AclImplTests {
@Test @Test
public void isSidLoadedBehavesAsExpected() { public void isSidLoadedBehavesAsExpected() {
List<Sid> loadedSids = Arrays.asList(new PrincipalSid("ben"), List<Sid> loadedSids = Arrays.asList(new PrincipalSid("ben"), new GrantedAuthoritySid("ROLE_IGNORED"));
new GrantedAuthoritySid("ROLE_IGNORED")); MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, loadedSids, true,
MutableAcl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, new PrincipalSid("joe"));
loadedSids, true, new PrincipalSid("joe"));
assertThat(acl.isSidLoaded(loadedSids)).isTrue(); assertThat(acl.isSidLoaded(loadedSids)).isTrue();
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new PrincipalSid("ben"))))
new PrincipalSid("ben")))) .isTrue();
.isTrue(); assertThat(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid("ROLE_IGNORED")))).isTrue();
assertThat(acl.isSidLoaded(Arrays.asList((Sid) new GrantedAuthoritySid(
"ROLE_IGNORED"))))
.isTrue();
assertThat(acl.isSidLoaded(BEN)).isTrue(); assertThat(acl.isSidLoaded(BEN)).isTrue();
assertThat(acl.isSidLoaded(null)).isTrue(); assertThat(acl.isSidLoaded(null)).isTrue();
assertThat(acl.isSidLoaded(new ArrayList<>(0))).isTrue(); assertThat(acl.isSidLoaded(new ArrayList<>(0))).isTrue();
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid( assertThat(acl.isSidLoaded(
"ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED")))) Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_IGNORED"))))
.isTrue(); .isTrue();
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid( assertThat(acl.isSidLoaded(
"ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED")))) Arrays.asList(new GrantedAuthoritySid("ROLE_GENERAL"), new GrantedAuthoritySid("ROLE_IGNORED"))))
.isFalse(); .isFalse();
assertThat(acl.isSidLoaded(Arrays.asList(new GrantedAuthoritySid( assertThat(acl.isSidLoaded(
"ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL")))) Arrays.asList(new GrantedAuthoritySid("ROLE_IGNORED"), new GrantedAuthoritySid("ROLE_GENERAL"))))
.isFalse(); .isFalse();
} }
@Test(expected = NotFoundException.class) @Test(expected = NotFoundException.class)
public void insertAceRaisesNotFoundExceptionForIndexLessThanZero() { public void insertAceRaisesNotFoundExceptionForIndexLessThanZero() {
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
acl.insertAce(-1, mock(Permission.class), mock(Sid.class), true); acl.insertAce(-1, mock(Permission.class), mock(Sid.class), true);
} }
@Test(expected = NotFoundException.class) @Test(expected = NotFoundException.class)
public void deleteAceRaisesNotFoundExceptionForIndexLessThanZero() { public void deleteAceRaisesNotFoundExceptionForIndexLessThanZero() {
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
acl.deleteAce(-1); acl.deleteAce(-1);
} }
@Test(expected = NotFoundException.class) @Test(expected = NotFoundException.class)
public void insertAceRaisesNotFoundExceptionForIndexGreaterThanSize() { public void insertAceRaisesNotFoundExceptionForIndexGreaterThanSize() {
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
// Insert at zero, OK. // Insert at zero, OK.
acl.insertAce(0, mock(Permission.class), mock(Sid.class), true); acl.insertAce(0, mock(Permission.class), mock(Sid.class), true);
// Size is now 1 // Size is now 1
@ -541,8 +488,7 @@ public class AclImplTests {
// SEC-1151 // SEC-1151
@Test(expected = NotFoundException.class) @Test(expected = NotFoundException.class)
public void deleteAceRaisesNotFoundExceptionForIndexEqualToSize() { public void deleteAceRaisesNotFoundExceptionForIndexEqualToSize() {
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, pgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe"));
acl.insertAce(0, mock(Permission.class), mock(Sid.class), true); acl.insertAce(0, mock(Permission.class), mock(Sid.class), true);
// Size is now 1 // Size is now 1
acl.deleteAce(1); acl.deleteAce(1);
@ -551,11 +497,9 @@ public class AclImplTests {
// SEC-1795 // SEC-1795
@Test @Test
public void changingParentIsSuccessful() { public void changingParentIsSuccessful() {
AclImpl parentAcl = new AclImpl(objectIdentity, 1L, authzStrategy, AclImpl parentAcl = new AclImpl(objectIdentity, 1L, authzStrategy, mockAuditLogger);
mockAuditLogger);
AclImpl childAcl = new AclImpl(objectIdentity, 2L, authzStrategy, mockAuditLogger); AclImpl childAcl = new AclImpl(objectIdentity, 2L, authzStrategy, mockAuditLogger);
AclImpl changeParentAcl = new AclImpl(objectIdentity, 3L, authzStrategy, AclImpl changeParentAcl = new AclImpl(objectIdentity, 3L, authzStrategy, mockAuditLogger);
mockAuditLogger);
childAcl.setParent(parentAcl); childAcl.setParent(parentAcl);
childAcl.setParent(changeParentAcl); childAcl.setParent(changeParentAcl);
@ -566,9 +510,9 @@ public class AclImplTests {
public void maskPermissionGrantingStrategy() { public void maskPermissionGrantingStrategy() {
DefaultPermissionGrantingStrategy maskPgs = new MaskPermissionGrantingStrategy(mockAuditLogger); DefaultPermissionGrantingStrategy maskPgs = new MaskPermissionGrantingStrategy(mockAuditLogger);
MockAclService service = new MockAclService(); MockAclService service = new MockAclService();
AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, maskPgs, null, null, AclImpl acl = new AclImpl(objectIdentity, 1, authzStrategy, maskPgs, null, null, true, new PrincipalSid("joe"));
true, new PrincipalSid("joe")); Permission permission = permissionFactory
Permission permission = permissionFactory.buildFromMask(BasePermission.READ.getMask() | BasePermission.WRITE.getMask()); .buildFromMask(BasePermission.READ.getMask() | BasePermission.WRITE.getMask());
Sid sid = new PrincipalSid("ben"); Sid sid = new PrincipalSid("ben");
acl.insertAce(0, permission, sid, true); acl.insertAce(0, permission, sid, true);
service.updateAcl(acl); service.updateAcl(acl);
@ -579,20 +523,20 @@ public class AclImplTests {
@Test @Test
public void hashCodeWithoutStackOverFlow() throws Exception { public void hashCodeWithoutStackOverFlow() throws Exception {
//given // given
Sid sid = new PrincipalSid("pSid"); Sid sid = new PrincipalSid("pSid");
ObjectIdentity oid = new ObjectIdentityImpl("type", 1); ObjectIdentity oid = new ObjectIdentityImpl("type", 1);
AclAuthorizationStrategy authStrategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("role")); AclAuthorizationStrategy authStrategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("role"));
PermissionGrantingStrategy grantingStrategy = new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()); PermissionGrantingStrategy grantingStrategy = new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
AclImpl acl = new AclImpl(oid, 1L, authStrategy, grantingStrategy, null, null, false, sid); AclImpl acl = new AclImpl(oid, 1L, authStrategy, grantingStrategy, null, null, false, sid);
AccessControlEntryImpl ace = new AccessControlEntryImpl(1L, acl, sid, BasePermission.READ, true, true, true); AccessControlEntryImpl ace = new AccessControlEntryImpl(1L, acl, sid, BasePermission.READ, true, true, true);
Field fieldAces = FieldUtils.getField(AclImpl.class, "aces"); Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
fieldAces.setAccessible(true); fieldAces.setAccessible(true);
List<AccessControlEntryImpl> aces = (List<AccessControlEntryImpl>) fieldAces.get(acl); List<AccessControlEntryImpl> aces = (List<AccessControlEntryImpl>) fieldAces.get(acl);
aces.add(ace); aces.add(ace);
//when - then none StackOverFlowError been raised // when - then none StackOverFlowError been raised
ace.hashCode(); ace.hashCode();
} }
@ -600,6 +544,7 @@ public class AclImplTests {
// ================================================================================================== // ==================================================================================================
private static class MaskPermissionGrantingStrategy extends DefaultPermissionGrantingStrategy { private static class MaskPermissionGrantingStrategy extends DefaultPermissionGrantingStrategy {
MaskPermissionGrantingStrategy(AuditLogger auditLogger) { MaskPermissionGrantingStrategy(AuditLogger auditLogger) {
super(auditLogger); super(auditLogger);
} }
@ -611,25 +556,24 @@ public class AclImplTests {
} }
return super.isGranted(ace, p); return super.isGranted(ace, p);
} }
} }
private class MockAclService implements MutableAclService { private class MockAclService implements MutableAclService {
public MutableAcl createAcl(ObjectIdentity objectIdentity)
throws AlreadyExistsException { public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException {
return null; return null;
} }
public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException {
throws ChildrenExistException {
} }
/* /*
* Mock implementation that populates the aces list with fully initialized * Mock implementation that populates the aces list with fully initialized
* AccessControlEntries * AccessControlEntries
* *
* @see * @see org.springframework.security.acls.MutableAclService#updateAcl(org.
* org.springframework.security.acls.MutableAclService#updateAcl(org.springframework * springframework .security.acls.MutableAcl)
* .security.acls.MutableAcl)
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException { public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
@ -645,9 +589,8 @@ public class AclImplTests {
AccessControlEntry ac = oldAces.get(i); AccessControlEntry ac = oldAces.get(i);
// Just give an ID to all this acl's aces, rest of the fields are just // Just give an ID to all this acl's aces, rest of the fields are just
// copied // copied
newAces.add(new AccessControlEntryImpl((i + 1), ac.getAcl(), ac newAces.add(new AccessControlEntryImpl((i + 1), ac.getAcl(), ac.getSid(), ac.getPermission(),
.getSid(), ac.getPermission(), ac.isGranting(), ac.isGranting(), ((AuditableAccessControlEntry) ac).isAuditSuccess(),
((AuditableAccessControlEntry) ac).isAuditSuccess(),
((AuditableAccessControlEntry) ac).isAuditFailure())); ((AuditableAccessControlEntry) ac).isAuditFailure()));
} }
} }
@ -666,19 +609,19 @@ public class AclImplTests {
return null; return null;
} }
public Acl readAclById(ObjectIdentity object, List<Sid> sids) public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
return null;
}
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException {
return null;
}
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
throws NotFoundException { throws NotFoundException {
return null; return null;
} }
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects)
throws NotFoundException {
return null;
}
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects,
List<Sid> sids) throws NotFoundException {
return null;
}
} }
} }

View File

@ -35,6 +35,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
* @author Andrei Stefan * @author Andrei Stefan
*/ */
public class AclImplementationSecurityCheckTests { public class AclImplementationSecurityCheckTests {
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
// ~ Methods // ~ Methods
@ -52,50 +53,42 @@ public class AclImplementationSecurityCheckTests {
@Test @Test
public void testSecurityCheckNoACEs() { public void testSecurityCheckNoACEs() {
Authentication auth = new TestingAuthenticationToken("user", "password", Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL", "ROLE_AUDITING",
"ROLE_GENERAL", "ROLE_AUDITING", "ROLE_OWNERSHIP"); "ROLE_OWNERSHIP");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); new SimpleGrantedAuthority("ROLE_GENERAL"));
Acl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, Acl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
new ConsoleAuditLogger());
aclAuthorizationStrategy.securityCheck(acl, aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL); aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_AUDITING);
aclAuthorizationStrategy.securityCheck(acl, aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
AclAuthorizationStrategy.CHANGE_AUDITING);
aclAuthorizationStrategy.securityCheck(acl,
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
// Create another authorization strategy // Create another authorization strategy
AclAuthorizationStrategy aclAuthorizationStrategy2 = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy2 = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"),
"ROLE_TWO"), new SimpleGrantedAuthority("ROLE_THREE")); new SimpleGrantedAuthority("ROLE_THREE"));
Acl acl2 = new AclImpl(identity, 1L, aclAuthorizationStrategy2, Acl acl2 = new AclImpl(identity, 1L, aclAuthorizationStrategy2, new ConsoleAuditLogger());
new ConsoleAuditLogger());
// Check access in case the principal has no authorization rights // Check access in case the principal has no authorization rights
try { try {
aclAuthorizationStrategy2.securityCheck(acl2, aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
} }
try { try {
aclAuthorizationStrategy2.securityCheck(acl2, aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_AUDITING);
AclAuthorizationStrategy.CHANGE_AUDITING);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
} }
try { try {
aclAuthorizationStrategy2.securityCheck(acl2, aclAuthorizationStrategy2.securityCheck(acl2, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -105,54 +98,46 @@ public class AclImplementationSecurityCheckTests {
@Test @Test
public void testSecurityCheckWithMultipleACEs() { public void testSecurityCheckWithMultipleACEs() {
// Create a simple authentication with ROLE_GENERAL // Create a simple authentication with ROLE_GENERAL
Authentication auth = new TestingAuthenticationToken("user", "password", Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
"ROLE_GENERAL");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
// Authorization strategy will require a different role for each access // Authorization strategy will require a different role for each access
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); new SimpleGrantedAuthority("ROLE_GENERAL"));
// Let's give the principal the ADMINISTRATION permission, without // Let's give the principal the ADMINISTRATION permission, without
// granting access // granting access
MutableAcl aclFirstDeny = new AclImpl(identity, 1L, MutableAcl aclFirstDeny = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
aclAuthorizationStrategy, new ConsoleAuditLogger()); aclFirstDeny.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), false);
aclFirstDeny.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth),
false);
// The CHANGE_GENERAL test should pass as the principal has ROLE_GENERAL // The CHANGE_GENERAL test should pass as the principal has ROLE_GENERAL
aclAuthorizationStrategy.securityCheck(aclFirstDeny, aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL);
// The CHANGE_AUDITING and CHANGE_OWNERSHIP should fail since the // The CHANGE_AUDITING and CHANGE_OWNERSHIP should fail since the
// principal doesn't have these authorities, // principal doesn't have these authorities,
// nor granting access // nor granting access
try { try {
aclAuthorizationStrategy.securityCheck(aclFirstDeny, aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING);
AclAuthorizationStrategy.CHANGE_AUDITING);
fail("It should have thrown AccessDeniedException"); fail("It should have thrown AccessDeniedException");
} }
catch (AccessDeniedException expected) { catch (AccessDeniedException expected) {
} }
try { try {
aclAuthorizationStrategy.securityCheck(aclFirstDeny, aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
fail("It should have thrown AccessDeniedException"); fail("It should have thrown AccessDeniedException");
} }
catch (AccessDeniedException expected) { catch (AccessDeniedException expected) {
} }
// Add granting access to this principal // Add granting access to this principal
aclFirstDeny.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), aclFirstDeny.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
true);
// and try again for CHANGE_AUDITING - the first ACE's granting flag // and try again for CHANGE_AUDITING - the first ACE's granting flag
// (false) will deny this access // (false) will deny this access
try { try {
aclAuthorizationStrategy.securityCheck(aclFirstDeny, aclAuthorizationStrategy.securityCheck(aclFirstDeny, AclAuthorizationStrategy.CHANGE_AUDITING);
AclAuthorizationStrategy.CHANGE_AUDITING);
fail("It should have thrown AccessDeniedException"); fail("It should have thrown AccessDeniedException");
} }
catch (AccessDeniedException expected) { catch (AccessDeniedException expected) {
@ -160,23 +145,18 @@ public class AclImplementationSecurityCheckTests {
// Create another ACL and give the principal the ADMINISTRATION // Create another ACL and give the principal the ADMINISTRATION
// permission, with granting access // permission, with granting access
MutableAcl aclFirstAllow = new AclImpl(identity, 1L, MutableAcl aclFirstAllow = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
aclAuthorizationStrategy, new ConsoleAuditLogger()); aclFirstAllow.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
aclFirstAllow.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth),
true);
// The CHANGE_AUDITING test should pass as there is one ACE with // The CHANGE_AUDITING test should pass as there is one ACE with
// granting access // granting access
aclAuthorizationStrategy.securityCheck(aclFirstAllow, aclAuthorizationStrategy.securityCheck(aclFirstAllow, AclAuthorizationStrategy.CHANGE_AUDITING);
AclAuthorizationStrategy.CHANGE_AUDITING);
// Add a deny ACE and test again for CHANGE_AUDITING // Add a deny ACE and test again for CHANGE_AUDITING
aclFirstAllow.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), aclFirstAllow.insertAce(1, BasePermission.ADMINISTRATION, new PrincipalSid(auth), false);
false);
try { try {
aclAuthorizationStrategy.securityCheck(aclFirstAllow, aclAuthorizationStrategy.securityCheck(aclFirstAllow, AclAuthorizationStrategy.CHANGE_AUDITING);
AclAuthorizationStrategy.CHANGE_AUDITING);
} }
catch (AccessDeniedException notExpected) { catch (AccessDeniedException notExpected) {
@ -184,11 +164,9 @@ public class AclImplementationSecurityCheckTests {
} }
// Create an ACL with no ACE // Create an ACL with no ACE
MutableAcl aclNoACE = new AclImpl(identity, 1L, MutableAcl aclNoACE = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
aclAuthorizationStrategy, new ConsoleAuditLogger());
try { try {
aclAuthorizationStrategy.securityCheck(aclNoACE, aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_AUDITING);
AclAuthorizationStrategy.CHANGE_AUDITING);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -196,8 +174,7 @@ public class AclImplementationSecurityCheckTests {
} }
// and still grant access for CHANGE_GENERAL // and still grant access for CHANGE_GENERAL
try { try {
aclAuthorizationStrategy.securityCheck(aclNoACE, aclAuthorizationStrategy.securityCheck(aclNoACE, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL);
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -208,31 +185,26 @@ public class AclImplementationSecurityCheckTests {
@Test @Test
public void testSecurityCheckWithInheritableACEs() { public void testSecurityCheckWithInheritableACEs() {
// Create a simple authentication with ROLE_GENERAL // Create a simple authentication with ROLE_GENERAL
Authentication auth = new TestingAuthenticationToken("user", "password", Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
"ROLE_GENERAL");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100);
// Authorization strategy will require a different role for each access // Authorization strategy will require a different role for each access
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_ONE"), new SimpleGrantedAuthority("ROLE_TWO"),
"ROLE_TWO"), new SimpleGrantedAuthority("ROLE_GENERAL")); new SimpleGrantedAuthority("ROLE_GENERAL"));
// Let's give the principal an ADMINISTRATION permission, with granting // Let's give the principal an ADMINISTRATION permission, with granting
// access // access
MutableAcl parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, MutableAcl parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger());
new ConsoleAuditLogger()); parentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
parentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), MutableAcl childAcl = new AclImpl(identity, 2, aclAuthorizationStrategy, new ConsoleAuditLogger());
true);
MutableAcl childAcl = new AclImpl(identity, 2, aclAuthorizationStrategy,
new ConsoleAuditLogger());
// Check against the 'child' acl, which doesn't offer any authorization // Check against the 'child' acl, which doesn't offer any authorization
// rights on CHANGE_OWNERSHIP // rights on CHANGE_OWNERSHIP
try { try {
aclAuthorizationStrategy.securityCheck(childAcl, aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
fail("It should have thrown NotFoundException"); fail("It should have thrown NotFoundException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -244,8 +216,7 @@ public class AclImplementationSecurityCheckTests {
childAcl.setParent(parentAcl); childAcl.setParent(parentAcl);
childAcl.setEntriesInheriting(true); childAcl.setEntriesInheriting(true);
try { try {
aclAuthorizationStrategy.securityCheck(childAcl, aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -253,18 +224,14 @@ public class AclImplementationSecurityCheckTests {
} }
// Create a root parent and link it to the middle parent // Create a root parent and link it to the middle parent
MutableAcl rootParentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, MutableAcl rootParentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger());
new ConsoleAuditLogger()); parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, new ConsoleAuditLogger());
parentAcl = new AclImpl(identity, 1, aclAuthorizationStrategy, rootParentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth), true);
new ConsoleAuditLogger());
rootParentAcl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(auth),
true);
parentAcl.setEntriesInheriting(true); parentAcl.setEntriesInheriting(true);
parentAcl.setParent(rootParentAcl); parentAcl.setParent(rootParentAcl);
childAcl.setParent(parentAcl); childAcl.setParent(parentAcl);
try { try {
aclAuthorizationStrategy.securityCheck(childAcl, aclAuthorizationStrategy.securityCheck(childAcl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
@ -274,39 +241,36 @@ public class AclImplementationSecurityCheckTests {
@Test @Test
public void testSecurityCheckPrincipalOwner() { public void testSecurityCheckPrincipalOwner() {
Authentication auth = new TestingAuthenticationToken("user", "password", Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_ONE");
"ROLE_ONE");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100);
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); new SimpleGrantedAuthority("ROLE_GENERAL"));
Acl acl = new AclImpl(identity, 1, aclAuthorizationStrategy, Acl acl = new AclImpl(identity, 1, aclAuthorizationStrategy,
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), null, new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), null, null, false,
null, false, new PrincipalSid(auth)); new PrincipalSid(auth));
try { try {
aclAuthorizationStrategy.securityCheck(acl, aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_GENERAL);
AclAuthorizationStrategy.CHANGE_GENERAL);
} }
catch (AccessDeniedException notExpected) { catch (AccessDeniedException notExpected) {
fail("It shouldn't have thrown AccessDeniedException"); fail("It shouldn't have thrown AccessDeniedException");
} }
try { try {
aclAuthorizationStrategy.securityCheck(acl, aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_AUDITING);
AclAuthorizationStrategy.CHANGE_AUDITING);
fail("It shouldn't have thrown AccessDeniedException"); fail("It shouldn't have thrown AccessDeniedException");
} }
catch (NotFoundException expected) { catch (NotFoundException expected) {
} }
try { try {
aclAuthorizationStrategy.securityCheck(acl, aclAuthorizationStrategy.securityCheck(acl, AclAuthorizationStrategy.CHANGE_OWNERSHIP);
AclAuthorizationStrategy.CHANGE_OWNERSHIP);
} }
catch (AccessDeniedException notExpected) { catch (AccessDeniedException notExpected) {
fail("It shouldn't have thrown AccessDeniedException"); fail("It shouldn't have thrown AccessDeniedException");
} }
} }
} }

View File

@ -33,11 +33,15 @@ import org.springframework.security.acls.model.AuditableAccessControlEntry;
* @author Andrei Stefan * @author Andrei Stefan
*/ */
public class AuditLoggerTests { public class AuditLoggerTests {
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private PrintStream console; private PrintStream console;
private ByteArrayOutputStream bytes = new ByteArrayOutputStream(); private ByteArrayOutputStream bytes = new ByteArrayOutputStream();
private ConsoleAuditLogger logger; private ConsoleAuditLogger logger;
private AuditableAccessControlEntry ace; private AuditableAccessControlEntry ace;
// ~ Methods // ~ Methods
@ -92,4 +96,5 @@ public class AuditLoggerTests {
logger.logIfNeeded(false, ace); logger.logIfNeeded(false, ace);
assertThat(bytes.toString()).startsWith("DENIED due to ACE"); assertThat(bytes.toString()).startsWith("DENIED due to ACE");
} }
} }

View File

@ -141,8 +141,7 @@ public class ObjectIdentityImplTests {
assertThat(obj).isNotEqualTo("DIFFERENT_OBJECT_TYPE"); assertThat(obj).isNotEqualTo("DIFFERENT_OBJECT_TYPE");
assertThat(obj).isNotEqualTo(new ObjectIdentityImpl(DOMAIN_CLASS, 2L)); assertThat(obj).isNotEqualTo(new ObjectIdentityImpl(DOMAIN_CLASS, 2L));
assertThat(obj).isNotEqualTo(new ObjectIdentityImpl( assertThat(obj).isNotEqualTo(new ObjectIdentityImpl(
"org.springframework.security.acls.domain.ObjectIdentityImplTests$MockOtherIdDomainObject", "org.springframework.security.acls.domain.ObjectIdentityImplTests$MockOtherIdDomainObject", 1L));
1L));
assertThat(new ObjectIdentityImpl(DOMAIN_CLASS, 1L)).isEqualTo(obj); assertThat(new ObjectIdentityImpl(DOMAIN_CLASS, 1L)).isEqualTo(obj);
assertThat(new ObjectIdentityImpl(mockObj)).isEqualTo(obj); assertThat(new ObjectIdentityImpl(mockObj)).isEqualTo(obj);
} }
@ -182,6 +181,7 @@ public class ObjectIdentityImplTests {
// ================================================================================================== // ==================================================================================================
private class MockIdDomainObject { private class MockIdDomainObject {
private Object id; private Object id;
public Object getId() { public Object getId() {
@ -191,9 +191,11 @@ public class ObjectIdentityImplTests {
public void setId(Object id) { public void setId(Object id) {
this.id = id; this.id = id;
} }
} }
private class MockOtherIdDomainObject { private class MockOtherIdDomainObject {
private Object id; private Object id;
public Object getId() { public Object getId() {
@ -203,5 +205,7 @@ public class ObjectIdentityImplTests {
public void setId(Object id) { public void setId(Object id) {
this.id = id; this.id = id;
} }
} }
} }

View File

@ -56,5 +56,7 @@ public class ObjectIdentityRetrievalStrategyImplTests {
public void setId(Object id) { public void setId(Object id) {
this.id = id; this.id = id;
} }
} }
} }

View File

@ -45,14 +45,10 @@ public class PermissionTests {
public void expectedIntegerValues() { public void expectedIntegerValues() {
assertThat(BasePermission.READ.getMask()).isEqualTo(1); assertThat(BasePermission.READ.getMask()).isEqualTo(1);
assertThat(BasePermission.ADMINISTRATION.getMask()).isEqualTo(16); assertThat(BasePermission.ADMINISTRATION.getMask()).isEqualTo(16);
assertThat( assertThat(new CumulativePermission().set(BasePermission.READ).set(BasePermission.WRITE)
new CumulativePermission().set(BasePermission.READ) .set(BasePermission.CREATE).getMask()).isEqualTo(7);
.set(BasePermission.WRITE).set(BasePermission.CREATE).getMask()) assertThat(new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION).getMask())
.isEqualTo(7); .isEqualTo(17);
assertThat(
new CumulativePermission().set(BasePermission.READ)
.set(BasePermission.ADMINISTRATION).getMask())
.isEqualTo(17);
} }
@Test @Test
@ -65,33 +61,28 @@ public class PermissionTests {
public void stringConversion() { public void stringConversion() {
permissionFactory.registerPublicPermissions(SpecialPermission.class); permissionFactory.registerPublicPermissions(SpecialPermission.class);
assertThat(BasePermission.READ.toString()) assertThat(BasePermission.READ.toString()).isEqualTo("BasePermission[...............................R=1]");
.isEqualTo("BasePermission[...............................R=1]");
assertThat(BasePermission.ADMINISTRATION.toString())
.isEqualTo("BasePermission[...........................A....=16]");
assertThat(new CumulativePermission().set(BasePermission.READ).toString())
.isEqualTo("CumulativePermission[...............................R=1]");
assertThat( assertThat(
BasePermission.ADMINISTRATION.toString()) new CumulativePermission().set(SpecialPermission.ENTER).set(BasePermission.ADMINISTRATION).toString())
.isEqualTo("BasePermission[...........................A....=16]"); .isEqualTo("CumulativePermission[..........................EA....=48]");
assertThat( assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ).toString())
new CumulativePermission().set(BasePermission.READ).toString()) .isEqualTo("CumulativePermission[...........................A...R=17]");
.isEqualTo("CumulativePermission[...............................R=1]");
assertThat(new CumulativePermission().set(SpecialPermission.ENTER) assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ)
.set(BasePermission.ADMINISTRATION).toString()) .clear(BasePermission.ADMINISTRATION).toString())
.isEqualTo("CumulativePermission[..........................EA....=48]"); .isEqualTo("CumulativePermission[...............................R=1]");
assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION) assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION).set(BasePermission.READ)
.set(BasePermission.READ).toString()) .clear(BasePermission.ADMINISTRATION).clear(BasePermission.READ).toString())
.isEqualTo("CumulativePermission[...........................A...R=17]"); .isEqualTo("CumulativePermission[................................=0]");
assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION)
.set(BasePermission.READ).clear(BasePermission.ADMINISTRATION)
.toString())
.isEqualTo("CumulativePermission[...............................R=1]");
assertThat(new CumulativePermission().set(BasePermission.ADMINISTRATION)
.set(BasePermission.READ).clear(BasePermission.ADMINISTRATION)
.clear(BasePermission.READ).toString())
.isEqualTo("CumulativePermission[................................=0]");
} }
} }

View File

@ -23,10 +23,13 @@ import org.springframework.security.acls.model.Permission;
* @author Ben Alex * @author Ben Alex
*/ */
public class SpecialPermission extends BasePermission { public class SpecialPermission extends BasePermission {
public static final Permission ENTER = new SpecialPermission(1 << 5, 'E'); // 32 public static final Permission ENTER = new SpecialPermission(1 << 5, 'E'); // 32
public static final Permission LEAVE = new SpecialPermission(1 << 6, 'L'); public static final Permission LEAVE = new SpecialPermission(1 << 6, 'L');
protected SpecialPermission(int mask, char code) { protected SpecialPermission(int mask, char code) {
super(mask, code); super(mask, code);
} }
} }

View File

@ -47,15 +47,20 @@ import javax.sql.DataSource;
public abstract class AbstractBasicLookupStrategyTests { public abstract class AbstractBasicLookupStrategyTests {
protected static final Sid BEN_SID = new PrincipalSid("ben"); protected static final Sid BEN_SID = new PrincipalSid("ben");
protected static final String TARGET_CLASS = TargetObject.class.getName(); protected static final String TARGET_CLASS = TargetObject.class.getName();
protected static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName(); protected static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName();
protected static final UUID OBJECT_IDENTITY_UUID = UUID.randomUUID(); protected static final UUID OBJECT_IDENTITY_UUID = UUID.randomUUID();
protected static final Long OBJECT_IDENTITY_LONG_AS_UUID = 110L; protected static final Long OBJECT_IDENTITY_LONG_AS_UUID = 110L;
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private BasicLookupStrategy strategy; private BasicLookupStrategy strategy;
private static CacheManager cacheManager; private static CacheManager cacheManager;
// ~ Methods // ~ Methods
@ -80,44 +85,41 @@ public abstract class AbstractBasicLookupStrategyTests {
@Before @Before
public void populateDatabase() { public void populateDatabase() {
String query = "INSERT INTO acl_sid(ID,PRINCIPAL,SID) VALUES (1,1,'ben');" String query = "INSERT INTO acl_sid(ID,PRINCIPAL,SID) VALUES (1,1,'ben');"
+ "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + TARGET_CLASS + "');" + "INSERT INTO acl_class(ID,CLASS) VALUES (2,'" + TARGET_CLASS + "');"
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);" + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (1,2,100,null,1,1);"
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);" + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (2,2,101,1,1,1);"
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);" + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (3,2,102,2,1,1);"
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);" + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (1,1,0,1,1,1,0,0);"
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);" + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (2,1,1,1,2,0,0,0);"
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);" + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (3,2,0,1,8,1,0,0);"
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);"; + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (4,3,0,1,8,0,0,0);";
getJdbcTemplate().execute(query); getJdbcTemplate().execute(query);
} }
@Before @Before
public void initializeBeans() { public void initializeBeans() {
strategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(), strategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(),
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
strategy.setPermissionFactory(new DefaultPermissionFactory()); strategy.setPermissionFactory(new DefaultPermissionFactory());
} }
protected AclAuthorizationStrategy aclAuthStrategy() { protected AclAuthorizationStrategy aclAuthStrategy() {
return new AclAuthorizationStrategyImpl( return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ADMINISTRATOR"));
new SimpleGrantedAuthority("ROLE_ADMINISTRATOR"));
} }
protected EhCacheBasedAclCache aclCache() { protected EhCacheBasedAclCache aclCache() {
return new EhCacheBasedAclCache(getCache(), return new EhCacheBasedAclCache(getCache(), new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
} }
@After @After
public void emptyDatabase() { public void emptyDatabase() {
String query = "DELETE FROM acl_entry;" + "DELETE FROM acl_object_identity WHERE ID = 9;" String query = "DELETE FROM acl_entry;" + "DELETE FROM acl_object_identity WHERE ID = 9;"
+ "DELETE FROM acl_object_identity WHERE ID = 8;" + "DELETE FROM acl_object_identity WHERE ID = 7;" + "DELETE FROM acl_object_identity WHERE ID = 8;" + "DELETE FROM acl_object_identity WHERE ID = 7;"
+ "DELETE FROM acl_object_identity WHERE ID = 6;" + "DELETE FROM acl_object_identity WHERE ID = 5;" + "DELETE FROM acl_object_identity WHERE ID = 6;" + "DELETE FROM acl_object_identity WHERE ID = 5;"
+ "DELETE FROM acl_object_identity WHERE ID = 4;" + "DELETE FROM acl_object_identity WHERE ID = 3;" + "DELETE FROM acl_object_identity WHERE ID = 4;" + "DELETE FROM acl_object_identity WHERE ID = 3;"
+ "DELETE FROM acl_object_identity WHERE ID = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;" + "DELETE FROM acl_object_identity WHERE ID = 2;" + "DELETE FROM acl_object_identity WHERE ID = 1;"
+ "DELETE FROM acl_class;" + "DELETE FROM acl_sid;"; + "DELETE FROM acl_class;" + "DELETE FROM acl_sid;";
getJdbcTemplate().execute(query); getJdbcTemplate().execute(query);
} }
@ -135,7 +137,7 @@ public abstract class AbstractBasicLookupStrategyTests {
ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102); ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102);
Map<ObjectIdentity, Acl> map = this.strategy Map<ObjectIdentity, Acl> map = this.strategy
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
checkEntries(topParentOid, middleParentOid, childOid, map); checkEntries(topParentOid, middleParentOid, childOid, map);
} }
@ -151,7 +153,7 @@ public abstract class AbstractBasicLookupStrategyTests {
// Let's empty the database to force acls retrieval from cache // Let's empty the database to force acls retrieval from cache
emptyDatabase(); emptyDatabase();
Map<ObjectIdentity, Acl> map = this.strategy Map<ObjectIdentity, Acl> map = this.strategy
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
checkEntries(topParentOid, middleParentOid, childOid, map); checkEntries(topParentOid, middleParentOid, childOid, map);
} }
@ -166,12 +168,12 @@ public abstract class AbstractBasicLookupStrategyTests {
// acls // acls
this.strategy.setBatchSize(1); this.strategy.setBatchSize(1);
Map<ObjectIdentity, Acl> map = this.strategy Map<ObjectIdentity, Acl> map = this.strategy
.readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null); .readAclsById(Arrays.asList(topParentOid, middleParentOid, childOid), null);
checkEntries(topParentOid, middleParentOid, childOid, map); checkEntries(topParentOid, middleParentOid, childOid, map);
} }
private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid, private void checkEntries(ObjectIdentity topParentOid, ObjectIdentity middleParentOid, ObjectIdentity childOid,
Map<ObjectIdentity, Acl> map) { Map<ObjectIdentity, Acl> map) {
assertThat(map).hasSize(3); assertThat(map).hasSize(3);
MutableAcl topParent = (MutableAcl) map.get(topParentOid); MutableAcl topParent = (MutableAcl) map.get(topParentOid);
@ -268,10 +270,10 @@ public abstract class AbstractBasicLookupStrategyTests {
@Test @Test
public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() { public void testReadAllObjectIdentitiesWhenLastElementIsAlreadyCached() {
String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,105,null,1,1);" String query = "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (6,2,105,null,1,1);"
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,106,6,1,1);" + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (7,2,106,6,1,1);"
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (8,2,107,6,1,1);" + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (8,2,107,6,1,1);"
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (9,2,108,7,1,1);" + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (9,2,108,7,1,1);"
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (7,6,0,1,1,1,0,0)"; + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (7,6,0,1,1,1,0,0)";
getJdbcTemplate().execute(query); getJdbcTemplate().execute(query);
ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 104L); ObjectIdentity grandParentOid = new ObjectIdentityImpl(TARGET_CLASS, 104L);
@ -302,7 +304,8 @@ public abstract class AbstractBasicLookupStrategyTests {
try { try {
foundAcls = strategy.readAclsById(allOids, sids); foundAcls = strategy.readAclsById(allOids, sids);
} catch (NotFoundException notExpected) { }
catch (NotFoundException notExpected) {
fail("It shouldn't have thrown NotFoundException"); fail("It shouldn't have thrown NotFoundException");
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.springframework.security.acls.jdbc; package org.springframework.security.acls.jdbc;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -34,17 +33,21 @@ import static org.mockito.BDDMockito.given;
/** /**
* Tests for {@link AclClassIdUtils}. * Tests for {@link AclClassIdUtils}.
*
* @author paulwheeler * @author paulwheeler
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class AclClassIdUtilsTests { public class AclClassIdUtilsTests {
private static final Long DEFAULT_IDENTIFIER = 999L; private static final Long DEFAULT_IDENTIFIER = 999L;
private static final BigInteger BIGINT_IDENTIFIER = new BigInteger("999"); private static final BigInteger BIGINT_IDENTIFIER = new BigInteger("999");
private static final String DEFAULT_IDENTIFIER_AS_STRING = DEFAULT_IDENTIFIER.toString(); private static final String DEFAULT_IDENTIFIER_AS_STRING = DEFAULT_IDENTIFIER.toString();
@Mock @Mock
private ResultSet resultSet; private ResultSet resultSet;
@Mock @Mock
private ConversionService conversionService; private ConversionService conversionService;
@ -172,4 +175,5 @@ public class AclClassIdUtilsTests {
// when // when
aclClassIdUtils.setConversionService(null); aclClassIdUtils.setConversionService(null);
} }
} }

View File

@ -28,8 +28,8 @@ import org.springframework.jdbc.core.JdbcTemplate;
* @author Paul Wheeler * @author Paul Wheeler
*/ */
public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests { public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests {
private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper();
private static final BasicLookupStrategyTestsDbHelper DATABASE_HELPER = new BasicLookupStrategyTestsDbHelper();
@BeforeClass @BeforeClass
public static void createDatabase() throws Exception { public static void createDatabase() throws Exception {
@ -50,4 +50,5 @@ public class BasicLookupStrategyTests extends AbstractBasicLookupStrategyTests {
public DataSource getDataSource() { public DataSource getDataSource() {
return DATABASE_HELPER.getDataSource(); return DATABASE_HELPER.getDataSource();
} }
} }

View File

@ -23,15 +23,20 @@ import org.springframework.util.FileCopyUtils;
/** /**
* Helper class to initialize the database for BasicLookupStrategyTests. * Helper class to initialize the database for BasicLookupStrategyTests.
*
* @author Andrei Stefan * @author Andrei Stefan
* @author Paul Wheeler * @author Paul Wheeler
*/ */
public class BasicLookupStrategyTestsDbHelper { public class BasicLookupStrategyTestsDbHelper {
private static final String ACL_SCHEMA_SQL_FILE = "createAclSchema.sql"; private static final String ACL_SCHEMA_SQL_FILE = "createAclSchema.sql";
private static final String ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID = "createAclSchemaWithAclClassIdType.sql"; private static final String ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID = "createAclSchemaWithAclClassIdType.sql";
private SingleConnectionDataSource dataSource; private SingleConnectionDataSource dataSource;
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
private boolean withAclClassIdType; private boolean withAclClassIdType;
public BasicLookupStrategyTestsDbHelper() { public BasicLookupStrategyTestsDbHelper() {
@ -48,7 +53,8 @@ public class BasicLookupStrategyTestsDbHelper {
if (!withAclClassIdType) { if (!withAclClassIdType) {
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytest"; connectionUrl = "jdbc:hsqldb:mem:lookupstrategytest";
sqlClassPathResource = ACL_SCHEMA_SQL_FILE; sqlClassPathResource = ACL_SCHEMA_SQL_FILE;
} else { }
else {
connectionUrl = "jdbc:hsqldb:mem:lookupstrategytestWithAclClassIdType"; connectionUrl = "jdbc:hsqldb:mem:lookupstrategytestWithAclClassIdType";
sqlClassPathResource = ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID; sqlClassPathResource = ACL_SCHEMA_SQL_FILE_WITH_ACL_CLASS_ID;
@ -69,4 +75,5 @@ public class BasicLookupStrategyTestsDbHelper {
public SingleConnectionDataSource getDataSource() { public SingleConnectionDataSource getDataSource() {
return dataSource; return dataSource;
} }
} }

View File

@ -71,7 +71,7 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku
public void initializeBeans() { public void initializeBeans() {
super.initializeBeans(); super.initializeBeans();
uuidEnabledStrategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(), uuidEnabledStrategy = new BasicLookupStrategy(getDataSource(), aclCache(), aclAuthStrategy(),
new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger())); new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()));
uuidEnabledStrategy.setPermissionFactory(new DefaultPermissionFactory()); uuidEnabledStrategy.setPermissionFactory(new DefaultPermissionFactory());
uuidEnabledStrategy.setAclClassIdSupported(true); uuidEnabledStrategy.setAclClassIdSupported(true);
uuidEnabledStrategy.setConversionService(new DefaultConversionService()); uuidEnabledStrategy.setConversionService(new DefaultConversionService());
@ -79,22 +79,22 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku
@Before @Before
public void populateDatabaseForAclClassTypeTests() { public void populateDatabaseForAclClassTypeTests() {
String query = "INSERT INTO acl_class(ID,CLASS,CLASS_ID_TYPE) VALUES (3,'" String query = "INSERT INTO acl_class(ID,CLASS,CLASS_ID_TYPE) VALUES (3,'" + TARGET_CLASS_WITH_UUID
+ TARGET_CLASS_WITH_UUID + "', 'java.util.UUID');"
+ "', 'java.util.UUID');" + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,3,'"
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (4,3,'" + OBJECT_IDENTITY_UUID.toString() + "',null,1,1);"
+ OBJECT_IDENTITY_UUID.toString() + "',null,1,1);" + "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,3,'"
+ "INSERT INTO acl_object_identity(ID,OBJECT_ID_CLASS,OBJECT_ID_IDENTITY,PARENT_OBJECT,OWNER_SID,ENTRIES_INHERITING) VALUES (5,3,'" + OBJECT_IDENTITY_LONG_AS_UUID + "',null,1,1);"
+ OBJECT_IDENTITY_LONG_AS_UUID + "',null,1,1);" + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,8,0,0,0);"
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (5,4,0,1,8,0,0,0);" + "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (6,5,0,1,8,0,0,0);";
+ "INSERT INTO acl_entry(ID,ACL_OBJECT_IDENTITY,ACE_ORDER,SID,MASK,GRANTING,AUDIT_SUCCESS,AUDIT_FAILURE) VALUES (6,5,0,1,8,0,0,0);";
DATABASE_HELPER.getJdbcTemplate().execute(query); DATABASE_HELPER.getJdbcTemplate().execute(query);
} }
@Test @Test
public void testReadObjectIdentityUsingUuidType() { public void testReadObjectIdentityUsingUuidType() {
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_UUID); ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_UUID);
Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid),
Arrays.asList(BEN_SID));
Assert.assertEquals(1, foundAcls.size()); Assert.assertEquals(1, foundAcls.size());
Assert.assertNotNull(foundAcls.get(oid)); Assert.assertNotNull(foundAcls.get(oid));
} }
@ -102,7 +102,8 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku
@Test @Test
public void testReadObjectIdentityUsingLongTypeWithConversionServiceEnabled() { public void testReadObjectIdentityUsingLongTypeWithConversionServiceEnabled() {
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 100L); ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); Map<ObjectIdentity, Acl> foundAcls = uuidEnabledStrategy.readAclsById(Arrays.asList(oid),
Arrays.asList(BEN_SID));
Assert.assertEquals(1, foundAcls.size()); Assert.assertEquals(1, foundAcls.size());
Assert.assertNotNull(foundAcls.get(oid)); Assert.assertNotNull(foundAcls.get(oid));
} }
@ -112,4 +113,5 @@ public class BasicLookupStrategyWithAclClassTypeTests extends AbstractBasicLooku
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_LONG_AS_UUID); ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, OBJECT_IDENTITY_LONG_AS_UUID);
uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID)); uuidEnabledStrategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
} }
} }

View File

@ -32,6 +32,7 @@ import javax.sql.DataSource;
* @author Ben Alex * @author Ben Alex
*/ */
public class DatabaseSeeder { public class DatabaseSeeder {
// ~ Constructors // ~ Constructors
// =================================================================================================== // ===================================================================================================
@ -43,4 +44,5 @@ public class DatabaseSeeder {
String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); String sql = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
template.execute(sql); template.execute(sql);
} }
} }

View File

@ -54,10 +54,12 @@ import org.springframework.test.util.ReflectionTestUtils;
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class EhCacheBasedAclCacheTests { public class EhCacheBasedAclCacheTests {
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
@Mock @Mock
private Ehcache cache; private Ehcache cache;
@Captor @Captor
private ArgumentCaptor<Element> element; private ArgumentCaptor<Element> element;
@ -67,17 +69,15 @@ public class EhCacheBasedAclCacheTests {
@Before @Before
public void setup() { public void setup() {
myCache = new EhCacheBasedAclCache(cache, new DefaultPermissionGrantingStrategy( myCache = new EhCacheBasedAclCache(cache, new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl( new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
new SimpleGrantedAuthority("ROLE_USER")));
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); new SimpleGrantedAuthority("ROLE_GENERAL"));
acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, new ConsoleAuditLogger());
new ConsoleAuditLogger());
} }
@After @After
@ -87,9 +87,8 @@ public class EhCacheBasedAclCacheTests {
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
public void constructorRejectsNullParameters() { public void constructorRejectsNullParameters() {
new EhCacheBasedAclCache(null, new DefaultPermissionGrantingStrategy( new EhCacheBasedAclCache(null, new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()),
new ConsoleAuditLogger()), new AclAuthorizationStrategyImpl( new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_USER")));
new SimpleGrantedAuthority("ROLE_USER")));
} }
@Test @Test
@ -152,12 +151,10 @@ public class EhCacheBasedAclCacheTests {
assertThat(retrieved).isEqualTo(acl); assertThat(retrieved).isEqualTo(acl);
Object retrieved1 = FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", Object retrieved1 = FieldUtils.getProtectedFieldValue("aclAuthorizationStrategy", retrieved);
retrieved);
assertThat(retrieved1).isNull(); assertThat(retrieved1).isNull();
Object retrieved2 = FieldUtils.getProtectedFieldValue( Object retrieved2 = FieldUtils.getProtectedFieldValue("permissionGrantingStrategy", retrieved);
"permissionGrantingStrategy", retrieved);
assertThat(retrieved2).isNull(); assertThat(retrieved2).isNull();
} }
@ -175,25 +172,21 @@ public class EhCacheBasedAclCacheTests {
verify(cache, times(2)).put(element.capture()); verify(cache, times(2)).put(element.capture());
assertThat(element.getValue().getKey()).isEqualTo(acl.getId()); assertThat(element.getValue().getKey()).isEqualTo(acl.getId());
assertThat(element.getValue().getObjectValue()).isEqualTo(acl); assertThat(element.getValue().getObjectValue()).isEqualTo(acl);
assertThat(element.getAllValues().get(0).getKey()).isEqualTo( assertThat(element.getAllValues().get(0).getKey()).isEqualTo(acl.getObjectIdentity());
acl.getObjectIdentity());
assertThat(element.getAllValues().get(0).getObjectValue()).isEqualTo(acl); assertThat(element.getAllValues().get(0).getObjectValue()).isEqualTo(acl);
} }
@Test @Test
public void putInCacheAclWithParent() { public void putInCacheAclWithParent() {
Authentication auth = new TestingAuthenticationToken("user", "password", Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
"ROLE_GENERAL");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, 2L);
2L);
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); new SimpleGrantedAuthority("ROLE_GENERAL"));
MutableAcl parentAcl = new AclImpl(identityParent, 2L, MutableAcl parentAcl = new AclImpl(identityParent, 2L, aclAuthorizationStrategy, new ConsoleAuditLogger());
aclAuthorizationStrategy, new ConsoleAuditLogger());
acl.setParent(parentAcl); acl.setParent(parentAcl);
myCache.putInCache(acl); myCache.putInCache(acl);
@ -233,10 +226,8 @@ public class EhCacheBasedAclCacheTests {
MutableAcl fromCache = myCache.getFromCache(acl.getId()); MutableAcl fromCache = myCache.getFromCache(acl.getId());
assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")) assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull();
.isNotNull(); assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull();
assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy"))
.isNotNull();
} }
@Test @Test
@ -248,8 +239,7 @@ public class EhCacheBasedAclCacheTests {
@Test @Test
public void getFromCacheObjectIdentityPopulatesTransient() { public void getFromCacheObjectIdentityPopulatesTransient() {
when(cache.get(acl.getObjectIdentity())) when(cache.get(acl.getObjectIdentity())).thenReturn(new Element(acl.getId(), acl));
.thenReturn(new Element(acl.getId(), acl));
myCache.putInCache(acl); myCache.putInCache(acl);
@ -258,16 +248,13 @@ public class EhCacheBasedAclCacheTests {
MutableAcl fromCache = myCache.getFromCache(acl.getObjectIdentity()); MutableAcl fromCache = myCache.getFromCache(acl.getObjectIdentity());
assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")) assertThat(ReflectionTestUtils.getField(fromCache, "aclAuthorizationStrategy")).isNotNull();
.isNotNull(); assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy")).isNotNull();
assertThat(ReflectionTestUtils.getField(fromCache, "permissionGrantingStrategy"))
.isNotNull();
} }
@Test @Test
public void evictCacheSerializable() { public void evictCacheSerializable() {
when(cache.get(acl.getObjectIdentity())) when(cache.get(acl.getObjectIdentity())).thenReturn(new Element(acl.getId(), acl));
.thenReturn(new Element(acl.getId(), acl));
myCache.evictFromCache(acl.getObjectIdentity()); myCache.evictFromCache(acl.getObjectIdentity());
@ -284,4 +271,5 @@ public class EhCacheBasedAclCacheTests {
verify(cache).remove(acl.getId()); verify(cache).remove(acl.getId());
verify(cache).remove(acl.getObjectIdentity()); verify(cache).remove(acl.getObjectIdentity());
} }
} }

View File

@ -41,8 +41,7 @@ import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
/** /**
* Unit and Integration tests the ACL JdbcAclService using an * Unit and Integration tests the ACL JdbcAclService using an in-memory database.
* in-memory database.
* *
* @author Nena Raab * @author Nena Raab
*/ */
@ -61,6 +60,7 @@ public class JdbcAclServiceTests {
JdbcOperations jdbcOperations; JdbcOperations jdbcOperations;
private JdbcAclService aclServiceIntegration; private JdbcAclService aclServiceIntegration;
private JdbcAclService aclService; private JdbcAclService aclService;
@Before @Before
@ -72,9 +72,7 @@ public class JdbcAclServiceTests {
@Before @Before
public void setUpEmbeddedDatabase() { public void setUpEmbeddedDatabase() {
embeddedDatabase = new EmbeddedDatabaseBuilder()// embeddedDatabase = new EmbeddedDatabaseBuilder()//
.addScript("createAclSchemaWithAclClassIdType.sql") .addScript("createAclSchemaWithAclClassIdType.sql").addScript("db/sql/test_data_hierarchy.sql").build();
.addScript("db/sql/test_data_hierarchy.sql")
.build();
} }
@After @After
@ -86,9 +84,7 @@ public class JdbcAclServiceTests {
@Test(expected = NotFoundException.class) @Test(expected = NotFoundException.class)
public void readAclByIdMissingAcl() { public void readAclByIdMissingAcl() {
Map<ObjectIdentity, Acl> result = new HashMap<>(); Map<ObjectIdentity, Acl> result = new HashMap<>();
when( when(lookupStrategy.readAclsById(anyList(), anyList())).thenReturn(result);
lookupStrategy.readAclsById(anyList(),
anyList())).thenReturn(result);
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 1); ObjectIdentity objectIdentity = new ObjectIdentityImpl(Object.class, 1);
List<Sid> sids = Arrays.<Sid>asList(new PrincipalSid("user")); List<Sid> sids = Arrays.<Sid>asList(new PrincipalSid("user"));
@ -99,10 +95,8 @@ public class JdbcAclServiceTests {
public void findOneChildren() { public void findOneChildren() {
List<ObjectIdentity> result = new ArrayList<>(); List<ObjectIdentity> result = new ArrayList<>();
result.add(new ObjectIdentityImpl(Object.class, "5577")); result.add(new ObjectIdentityImpl(Object.class, "5577"));
Object[] args = {"1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject"}; Object[] args = { "1", "org.springframework.security.acls.jdbc.JdbcAclServiceTests$MockLongIdDomainObject" };
when( when(jdbcOperations.query(anyString(), aryEq(args), any(RowMapper.class))).thenReturn(result);
jdbcOperations.query(anyString(),
aryEq(args), any(RowMapper.class))).thenReturn(result);
ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L); ObjectIdentity objectIdentity = new ObjectIdentityImpl(MockLongIdDomainObject.class, 1L);
List<ObjectIdentity> objectIdentities = aclService.findChildren(objectIdentity); List<ObjectIdentity> objectIdentities = aclService.findChildren(objectIdentity);
@ -170,10 +164,12 @@ public class JdbcAclServiceTests {
List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity); List<ObjectIdentity> objectIdentities = aclServiceIntegration.findChildren(objectIdentity);
assertThat(objectIdentities.size()).isEqualTo(1); assertThat(objectIdentities.size()).isEqualTo(1);
assertThat(objectIdentities.get(0).getType()).isEqualTo("costcenter"); assertThat(objectIdentities.get(0).getType()).isEqualTo("costcenter");
assertThat(objectIdentities.get(0).getIdentifier()).isEqualTo(UUID.fromString("25d93b3f-c3aa-4814-9d5e-c7c96ced7762")); assertThat(objectIdentities.get(0).getIdentifier())
.isEqualTo(UUID.fromString("25d93b3f-c3aa-4814-9d5e-c7c96ced7762"));
} }
private class MockLongIdDomainObject { private class MockLongIdDomainObject {
private Object id; private Object id;
public Object getId() { public Object getId() {
@ -183,9 +179,11 @@ public class JdbcAclServiceTests {
public void setId(Object id) { public void setId(Object id) {
this.id = id; this.id = id;
} }
} }
private class MockUntypedIdDomainObject { private class MockUntypedIdDomainObject {
private Object id; private Object id;
public Object getId() { public Object getId() {
@ -195,5 +193,7 @@ public class JdbcAclServiceTests {
public void setId(Object id) { public void setId(Object id) {
this.id = id; this.id = id;
} }
} }
} }

View File

@ -62,36 +62,38 @@ import org.springframework.transaction.annotation.Transactional;
* @author Andrei Stefan * @author Andrei Stefan
*/ */
@ContextConfiguration(locations = { "/jdbcMutableAclServiceTests-context.xml" }) @ContextConfiguration(locations = { "/jdbcMutableAclServiceTests-context.xml" })
public class JdbcMutableAclServiceTests extends public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4SpringContextTests {
AbstractTransactionalJUnit4SpringContextTests {
// ~ Constant fields // ~ Constant fields
// ================================================================================================ // ================================================================================================
private static final String TARGET_CLASS = TargetObject.class.getName(); private static final String TARGET_CLASS = TargetObject.class.getName();
private final Authentication auth = new TestingAuthenticationToken("ben", "ignored", private final Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR");
"ROLE_ADMINISTRATOR");
public static final String SELECT_ALL_CLASSES = "SELECT * FROM acl_class WHERE class = ?"; public static final String SELECT_ALL_CLASSES = "SELECT * FROM acl_class WHERE class = ?";
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
100L);
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS, 101L);
101L);
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS, 102L);
102L);
@Autowired @Autowired
private JdbcMutableAclService jdbcMutableAclService; private JdbcMutableAclService jdbcMutableAclService;
@Autowired @Autowired
private AclCache aclCache; private AclCache aclCache;
@Autowired @Autowired
private LookupStrategy lookupStrategy; private LookupStrategy lookupStrategy;
@Autowired @Autowired
private DataSource dataSource; private DataSource dataSource;
@Autowired @Autowired
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
@ -166,8 +168,8 @@ public class JdbcMutableAclServiceTests extends
jdbcMutableAclService.updateAcl(child); jdbcMutableAclService.updateAcl(child);
// Let's check if we can read them back correctly // Let's check if we can read them back correctly
Map<ObjectIdentity, Acl> map = jdbcMutableAclService.readAclsById(Arrays.asList( Map<ObjectIdentity, Acl> map = jdbcMutableAclService
getTopParentOid(), getMiddleParentOid(), getChildOid())); .readAclsById(Arrays.asList(getTopParentOid(), getMiddleParentOid(), getChildOid()));
assertThat(map).hasSize(3); assertThat(map).hasSize(3);
// Replace our current objects with their retrieved versions // Replace our current objects with their retrieved versions
@ -257,8 +259,9 @@ public class JdbcMutableAclServiceTests extends
} }
// Check the permissions are as they should be // Check the permissions are as they should be
assertThat(child.isGranted(delete, pSid, true)).isFalse(); // as earlier permission assertThat(child.isGranted(delete, pSid, true)).isFalse(); // as earlier
// overrode // permission
// overrode
assertThat(child.isGranted(Arrays.asList(BasePermission.CREATE), pSid, true)).isTrue(); assertThat(child.isGranted(Arrays.asList(BasePermission.CREATE), pSid, true)).isTrue();
// Now check the first ACE (index 0) really is DELETE for our Sid and is // Now check the first ACE (index 0) really is DELETE for our Sid and is
@ -360,8 +363,7 @@ public class JdbcMutableAclServiceTests extends
@Transactional @Transactional
public void createAclForADuplicateDomainObject() { public void createAclForADuplicateDomainObject() {
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS, ObjectIdentity duplicateOid = new ObjectIdentityImpl(TARGET_CLASS, 100L);
100L);
jdbcMutableAclService.createAcl(duplicateOid); jdbcMutableAclService.createAcl(duplicateOid);
// Try to add the same object second time // Try to add the same object second time
try { try {
@ -419,11 +421,8 @@ public class JdbcMutableAclServiceTests extends
// Remove the child and check all related database rows were removed accordingly // Remove the child and check all related database rows were removed accordingly
jdbcMutableAclService.deleteAcl(getChildOid(), false); jdbcMutableAclService.deleteAcl(getChildOid(), false);
assertThat( assertThat(jdbcTemplate.queryForList(SELECT_ALL_CLASSES, new Object[] { getTargetClass() })).hasSize(1);
jdbcTemplate.queryForList(SELECT_ALL_CLASSES, assertThat(jdbcTemplate.queryForList("select * from acl_object_identity")).isEmpty();
new Object[] { getTargetClass() })).hasSize(1);
assertThat(jdbcTemplate.queryForList("select * from acl_object_identity")
).isEmpty();
assertThat(jdbcTemplate.queryForList("select * from acl_entry")).isEmpty(); assertThat(jdbcTemplate.queryForList("select * from acl_entry")).isEmpty();
// Check the cache // Check the cache
@ -439,8 +438,7 @@ public class JdbcMutableAclServiceTests extends
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 101); ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS, 101);
jdbcMutableAclService.createAcl(oid); jdbcMutableAclService.createAcl(oid);
assertThat(jdbcMutableAclService.readAclById(new ObjectIdentityImpl( assertThat(jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, 101L))).isNotNull();
TARGET_CLASS, 101L))).isNotNull();
} }
/** /**
@ -449,8 +447,7 @@ public class JdbcMutableAclServiceTests extends
@Test @Test
@Transactional @Transactional
public void childrenAreClearedFromCacheWhenParentIsUpdated() { public void childrenAreClearedFromCacheWhenParentIsUpdated() {
Authentication auth = new TestingAuthenticationToken("ben", "ignored", Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR");
"ROLE_ADMINISTRATOR");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
@ -474,7 +471,8 @@ public class JdbcMutableAclServiceTests extends
child = (MutableAcl) jdbcMutableAclService.readAclById(childOid); child = (MutableAcl) jdbcMutableAclService.readAclById(childOid);
parent = (MutableAcl) child.getParentAcl(); parent = (MutableAcl) child.getParentAcl();
assertThat(parent.getEntries()).hasSize(2).withFailMessage("Fails because child has a stale reference to its parent"); assertThat(parent.getEntries()).hasSize(2)
.withFailMessage("Fails because child has a stale reference to its parent");
assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(1); assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(1);
assertThat(parent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben")); assertThat(parent.getEntries().get(0).getSid()).isEqualTo(new PrincipalSid("ben"));
assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(1); assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(1);
@ -487,34 +485,28 @@ public class JdbcMutableAclServiceTests extends
@Test @Test
@Transactional @Transactional
public void childrenAreClearedFromCacheWhenParentisUpdated2() { public void childrenAreClearedFromCacheWhenParentisUpdated2() {
Authentication auth = new TestingAuthenticationToken("system", "secret", Authentication auth = new TestingAuthenticationToken("system", "secret", "ROLE_IGNORED");
"ROLE_IGNORED");
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentityImpl rootObject = new ObjectIdentityImpl(TARGET_CLASS, ObjectIdentityImpl rootObject = new ObjectIdentityImpl(TARGET_CLASS, 1L);
1L);
MutableAcl parent = jdbcMutableAclService.createAcl(rootObject); MutableAcl parent = jdbcMutableAclService.createAcl(rootObject);
MutableAcl child = jdbcMutableAclService.createAcl(new ObjectIdentityImpl( MutableAcl child = jdbcMutableAclService.createAcl(new ObjectIdentityImpl(TARGET_CLASS, 2L));
TARGET_CLASS, 2L));
child.setParent(parent); child.setParent(parent);
jdbcMutableAclService.updateAcl(child); jdbcMutableAclService.updateAcl(child);
parent.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid( parent.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid("ROLE_ADMINISTRATOR"), true);
"ROLE_ADMINISTRATOR"), true);
jdbcMutableAclService.updateAcl(parent); jdbcMutableAclService.updateAcl(parent);
parent.insertAce(1, BasePermission.DELETE, new PrincipalSid("terry"), true); parent.insertAce(1, BasePermission.DELETE, new PrincipalSid("terry"), true);
jdbcMutableAclService.updateAcl(parent); jdbcMutableAclService.updateAcl(parent);
child = (MutableAcl) jdbcMutableAclService.readAclById(new ObjectIdentityImpl( child = (MutableAcl) jdbcMutableAclService.readAclById(new ObjectIdentityImpl(TARGET_CLASS, 2L));
TARGET_CLASS, 2L));
parent = (MutableAcl) child.getParentAcl(); parent = (MutableAcl) child.getParentAcl();
assertThat(parent.getEntries()).hasSize(2); assertThat(parent.getEntries()).hasSize(2);
assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(16); assertThat(parent.getEntries().get(0).getPermission().getMask()).isEqualTo(16);
assertThat(parent.getEntries() assertThat(parent.getEntries().get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"));
.get(0).getSid()).isEqualTo(new GrantedAuthoritySid("ROLE_ADMINISTRATOR"));
assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(8); assertThat(parent.getEntries().get(1).getPermission().getMask()).isEqualTo(8);
assertThat(parent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("terry")); assertThat(parent.getEntries().get(1).getSid()).isEqualTo(new PrincipalSid("terry"));
} }
@ -522,18 +514,15 @@ public class JdbcMutableAclServiceTests extends
@Test @Test
@Transactional @Transactional
public void cumulativePermissions() { public void cumulativePermissions() {
Authentication auth = new TestingAuthenticationToken("ben", "ignored", Authentication auth = new TestingAuthenticationToken("ben", "ignored", "ROLE_ADMINISTRATOR");
"ROLE_ADMINISTRATOR");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS, 110L);
110L);
MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid); MutableAcl topParent = jdbcMutableAclService.createAcl(topParentOid);
// Add an ACE permission entry // Add an ACE permission entry
Permission cm = new CumulativePermission().set(BasePermission.READ).set( Permission cm = new CumulativePermission().set(BasePermission.READ).set(BasePermission.ADMINISTRATION);
BasePermission.ADMINISTRATION);
assertThat(cm.getMask()).isEqualTo(17); assertThat(cm.getMask()).isEqualTo(17);
Sid benSid = new PrincipalSid(auth); Sid benSid = new PrincipalSid(auth);
topParent.insertAce(0, cm, benSid, true); topParent.insertAce(0, cm, benSid, true);
@ -551,15 +540,12 @@ public class JdbcMutableAclServiceTests extends
@Test @Test
public void testProcessingCustomSid() { public void testProcessingCustomSid() {
CustomJdbcMutableAclService customJdbcMutableAclService = spy(new CustomJdbcMutableAclService( CustomJdbcMutableAclService customJdbcMutableAclService = spy(
dataSource, lookupStrategy, aclCache)); new CustomJdbcMutableAclService(dataSource, lookupStrategy, aclCache));
CustomSid customSid = new CustomSid("Custom sid"); CustomSid customSid = new CustomSid("Custom sid");
when( when(customJdbcMutableAclService.createOrRetrieveSidPrimaryKey("Custom sid", false, false)).thenReturn(1L);
customJdbcMutableAclService.createOrRetrieveSidPrimaryKey("Custom sid",
false, false)).thenReturn(1L);
Long result = customJdbcMutableAclService.createOrRetrieveSidPrimaryKey( Long result = customJdbcMutableAclService.createOrRetrieveSidPrimaryKey(customSid, false);
customSid, false);
assertThat(new Long(1L)).isEqualTo(result); assertThat(new Long(1L)).isEqualTo(result);
} }
@ -570,8 +556,7 @@ public class JdbcMutableAclServiceTests extends
*/ */
private class CustomJdbcMutableAclService extends JdbcMutableAclService { private class CustomJdbcMutableAclService extends JdbcMutableAclService {
private CustomJdbcMutableAclService(DataSource dataSource, private CustomJdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
LookupStrategy lookupStrategy, AclCache aclCache) {
super(dataSource, lookupStrategy, aclCache); super(dataSource, lookupStrategy, aclCache);
} }
@ -591,6 +576,7 @@ public class JdbcMutableAclServiceTests extends
} }
return createOrRetrieveSidPrimaryKey(sidName, isPrincipal, allowCreate); return createOrRetrieveSidPrimaryKey(sidName, isPrincipal, allowCreate);
} }
} }
protected Authentication getAuth() { protected Authentication getAuth() {
@ -600,4 +586,5 @@ public class JdbcMutableAclServiceTests extends
protected JdbcMutableAclService getJdbcMutableAclService() { protected JdbcMutableAclService getJdbcMutableAclService() {
return jdbcMutableAclService; return jdbcMutableAclService;
} }
} }

View File

@ -28,20 +28,21 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
* Integration tests the ACL system using ACL class id type of UUID and using an in-memory database. * Integration tests the ACL system using ACL class id type of UUID and using an in-memory
* database.
*
* @author Paul Wheeler * @author Paul Wheeler
*/ */
@ContextConfiguration(locations = {"/jdbcMutableAclServiceTestsWithAclClass-context.xml"}) @ContextConfiguration(locations = { "/jdbcMutableAclServiceTestsWithAclClass-context.xml" })
public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServiceTests { public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServiceTests {
private static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName(); private static final String TARGET_CLASS_WITH_UUID = TargetObjectWithUUID.class.getName();
private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, private final ObjectIdentity topParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, UUID.randomUUID());
UUID.randomUUID());
private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, private final ObjectIdentity middleParentOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, UUID.randomUUID());
UUID.randomUUID());
private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, private final ObjectIdentity childOid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, UUID.randomUUID());
UUID.randomUUID());
@Override @Override
protected String getSqlClassPathResource() { protected String getSqlClassPathResource() {
@ -77,7 +78,8 @@ public class JdbcMutableAclServiceTestsWithAclClassId extends JdbcMutableAclServ
ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id); ObjectIdentity oid = new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id);
getJdbcMutableAclService().createAcl(oid); getJdbcMutableAclService().createAcl(oid);
assertThat(getJdbcMutableAclService().readAclById(new ObjectIdentityImpl( assertThat(getJdbcMutableAclService().readAclById(new ObjectIdentityImpl(TARGET_CLASS_WITH_UUID, id)))
TARGET_CLASS_WITH_UUID, id))).isNotNull(); .isNotNull();
} }
} }

View File

@ -41,6 +41,7 @@ import static org.assertj.core.api.Assertions.*;
* @author Marten Deinum * @author Marten Deinum
*/ */
public class SpringCacheBasedAclCacheTests { public class SpringCacheBasedAclCacheTests {
private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject"; private static final String TARGET_CLASS = "org.springframework.security.acls.TargetObject";
private static CacheManager cacheManager; private static CacheManager cacheManager;
@ -76,16 +77,14 @@ public class SpringCacheBasedAclCacheTests {
Map realCache = (Map) cache.getNativeCache(); Map realCache = (Map) cache.getNativeCache();
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 100L);
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); new SimpleGrantedAuthority("ROLE_GENERAL"));
AuditLogger auditLogger = new ConsoleAuditLogger(); AuditLogger auditLogger = new ConsoleAuditLogger();
PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy( PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger);
auditLogger); SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, permissionGrantingStrategy,
SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, aclAuthorizationStrategy);
permissionGrantingStrategy, aclAuthorizationStrategy); MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, auditLogger);
MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy,
auditLogger);
assertThat(realCache).isEmpty(); assertThat(realCache).isEmpty();
myCache.putInCache(acl); myCache.putInCache(acl);
@ -96,8 +95,7 @@ public class SpringCacheBasedAclCacheTests {
// Put another object in cache // Put another object in cache
ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, 101L); ObjectIdentity identity2 = new ObjectIdentityImpl(TARGET_CLASS, 101L);
MutableAcl acl2 = new AclImpl(identity2, 2L, MutableAcl acl2 = new AclImpl(identity2, 2L, aclAuthorizationStrategy, new ConsoleAuditLogger());
aclAuthorizationStrategy, new ConsoleAuditLogger());
myCache.putInCache(acl2); myCache.putInCache(acl2);
@ -123,28 +121,23 @@ public class SpringCacheBasedAclCacheTests {
Cache cache = getCache(); Cache cache = getCache();
Map realCache = (Map) cache.getNativeCache(); Map realCache = (Map) cache.getNativeCache();
Authentication auth = new TestingAuthenticationToken("user", "password", Authentication auth = new TestingAuthenticationToken("user", "password", "ROLE_GENERAL");
"ROLE_GENERAL");
auth.setAuthenticated(true); auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth); SecurityContextHolder.getContext().setAuthentication(auth);
ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 1L); ObjectIdentity identity = new ObjectIdentityImpl(TARGET_CLASS, 1L);
ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, ObjectIdentity identityParent = new ObjectIdentityImpl(TARGET_CLASS, 2L);
2L);
AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl( AclAuthorizationStrategy aclAuthorizationStrategy = new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority( new SimpleGrantedAuthority("ROLE_OWNERSHIP"), new SimpleGrantedAuthority("ROLE_AUDITING"),
"ROLE_AUDITING"), new SimpleGrantedAuthority("ROLE_GENERAL")); new SimpleGrantedAuthority("ROLE_GENERAL"));
AuditLogger auditLogger = new ConsoleAuditLogger(); AuditLogger auditLogger = new ConsoleAuditLogger();
PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy( PermissionGrantingStrategy permissionGrantingStrategy = new DefaultPermissionGrantingStrategy(auditLogger);
auditLogger); SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, permissionGrantingStrategy,
SpringCacheBasedAclCache myCache = new SpringCacheBasedAclCache(cache, aclAuthorizationStrategy);
permissionGrantingStrategy, aclAuthorizationStrategy);
MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, MutableAcl acl = new AclImpl(identity, 1L, aclAuthorizationStrategy, auditLogger);
auditLogger); MutableAcl parentAcl = new AclImpl(identityParent, 2L, aclAuthorizationStrategy, auditLogger);
MutableAcl parentAcl = new AclImpl(identityParent, 2L,
aclAuthorizationStrategy, auditLogger);
acl.setParent(parentAcl); acl.setParent(parentAcl);
@ -156,16 +149,14 @@ public class SpringCacheBasedAclCacheTests {
AclImpl aclFromCache = (AclImpl) myCache.getFromCache(1L); AclImpl aclFromCache = (AclImpl) myCache.getFromCache(1L);
assertThat(aclFromCache).isEqualTo(acl); assertThat(aclFromCache).isEqualTo(acl);
// SEC-951 check transient fields are set on parent // SEC-951 check transient fields are set on parent
assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "aclAuthorizationStrategy")).isNotNull();
"aclAuthorizationStrategy")).isNotNull(); assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(), "permissionGrantingStrategy")).isNotNull();
assertThat(FieldUtils.getFieldValue(aclFromCache.getParentAcl(),
"permissionGrantingStrategy")).isNotNull();
assertThat(myCache.getFromCache(identity)).isEqualTo(acl); assertThat(myCache.getFromCache(identity)).isEqualTo(acl);
assertThat(FieldUtils.getFieldValue(aclFromCache, "aclAuthorizationStrategy")).isNotNull(); assertThat(FieldUtils.getFieldValue(aclFromCache, "aclAuthorizationStrategy")).isNotNull();
AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(2L); AclImpl parentAclFromCache = (AclImpl) myCache.getFromCache(2L);
assertThat(parentAclFromCache).isEqualTo(parentAcl); assertThat(parentAclFromCache).isEqualTo(parentAcl);
assertThat(FieldUtils.getFieldValue(parentAclFromCache, assertThat(FieldUtils.getFieldValue(parentAclFromCache, "aclAuthorizationStrategy")).isNotNull();
"aclAuthorizationStrategy")).isNotNull();
assertThat(myCache.getFromCache(identityParent)).isEqualTo(parentAcl); assertThat(myCache.getFromCache(identityParent)).isEqualTo(parentAcl);
} }
} }

View File

@ -19,6 +19,7 @@ import org.springframework.security.acls.model.Sid;
/** /**
* This class is example of custom {@link Sid} implementation * This class is example of custom {@link Sid} implementation
*
* @author Mikhail Stryzhonok * @author Mikhail Stryzhonok
*/ */
public class CustomSid implements Sid { public class CustomSid implements Sid {
@ -36,4 +37,5 @@ public class CustomSid implements Sid {
public void setSid(String sid) { public void setSid(String sid) {
this.sid = sid; this.sid = sid;
} }
} }

View File

@ -39,8 +39,8 @@ import org.springframework.security.core.authority.AuthorityUtils;
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class SidRetrievalStrategyTests { public class SidRetrievalStrategyTests {
Authentication authentication = new TestingAuthenticationToken("scott", "password",
"A", "B", "C"); Authentication authentication = new TestingAuthenticationToken("scott", "password", "A", "B", "C");
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
@ -69,8 +69,7 @@ public class SidRetrievalStrategyTests {
public void roleHierarchyIsUsedWhenSet() { public void roleHierarchyIsUsedWhenSet() {
RoleHierarchy rh = mock(RoleHierarchy.class); RoleHierarchy rh = mock(RoleHierarchy.class);
List rhAuthorities = AuthorityUtils.createAuthorityList("D"); List rhAuthorities = AuthorityUtils.createAuthorityList("D");
when(rh.getReachableGrantedAuthorities(anyCollection())) when(rh.getReachableGrantedAuthorities(anyCollection())).thenReturn(rhAuthorities);
.thenReturn(rhAuthorities);
SidRetrievalStrategy strat = new SidRetrievalStrategyImpl(rh); SidRetrievalStrategy strat = new SidRetrievalStrategyImpl(rh);
List<Sid> sids = strat.getSids(authentication); List<Sid> sids = strat.getSids(authentication);
@ -79,4 +78,5 @@ public class SidRetrievalStrategyTests {
assertThat(sids.get(0) instanceof PrincipalSid).isTrue(); assertThat(sids.get(0) instanceof PrincipalSid).isTrue();
assertThat(((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()).isEqualTo("D"); assertThat(((GrantedAuthoritySid) sids.get(1)).getGrantedAuthority()).isEqualTo("D");
} }
} }

View File

@ -67,16 +67,14 @@ public class SidTests {
} }
try { try {
Authentication authentication = new TestingAuthenticationToken(null, Authentication authentication = new TestingAuthenticationToken(null, "password");
"password");
new PrincipalSid(authentication); new PrincipalSid(authentication);
fail("It should have thrown IllegalArgumentException"); fail("It should have thrown IllegalArgumentException");
} }
catch (IllegalArgumentException expected) { catch (IllegalArgumentException expected) {
} }
Authentication authentication = new TestingAuthenticationToken("johndoe", Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
"password");
new PrincipalSid(authentication); new PrincipalSid(authentication);
// throws no exception // throws no exception
} }
@ -140,18 +138,15 @@ public class SidTests {
@Test @Test
public void testPrincipalSidEquals() { public void testPrincipalSidEquals() {
Authentication authentication = new TestingAuthenticationToken("johndoe", Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
"password");
Sid principalSid = new PrincipalSid(authentication); Sid principalSid = new PrincipalSid(authentication);
assertThat(principalSid.equals(null)).isFalse(); assertThat(principalSid.equals(null)).isFalse();
assertThat(principalSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse(); assertThat(principalSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse();
assertThat(principalSid.equals(principalSid)).isTrue(); assertThat(principalSid.equals(principalSid)).isTrue();
assertThat(principalSid.equals(new PrincipalSid(authentication))).isTrue(); assertThat(principalSid.equals(new PrincipalSid(authentication))).isTrue();
assertThat(principalSid.equals(new PrincipalSid( assertThat(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("johndoe", null)))).isTrue();
new TestingAuthenticationToken("johndoe", null)))).isTrue(); assertThat(principalSid.equals(new PrincipalSid(new TestingAuthenticationToken("scott", null)))).isFalse();
assertThat(principalSid.equals(new PrincipalSid(
new TestingAuthenticationToken("scott", null)))).isFalse();
assertThat(principalSid.equals(new PrincipalSid("johndoe"))).isTrue(); assertThat(principalSid.equals(new PrincipalSid("johndoe"))).isTrue();
assertThat(principalSid.equals(new PrincipalSid("scott"))).isFalse(); assertThat(principalSid.equals(new PrincipalSid("scott"))).isFalse();
} }
@ -165,27 +160,22 @@ public class SidTests {
assertThat(gaSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse(); assertThat(gaSid.equals("DIFFERENT_TYPE_OBJECT")).isFalse();
assertThat(gaSid.equals(gaSid)).isTrue(); assertThat(gaSid.equals(gaSid)).isTrue();
assertThat(gaSid.equals(new GrantedAuthoritySid(ga))).isTrue(); assertThat(gaSid.equals(new GrantedAuthoritySid(ga))).isTrue();
assertThat(gaSid.equals(new GrantedAuthoritySid( assertThat(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST")))).isTrue();
new SimpleGrantedAuthority("ROLE_TEST")))).isTrue(); assertThat(gaSid.equals(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_NOT_EQUAL")))).isFalse();
assertThat(gaSid.equals(new GrantedAuthoritySid(
new SimpleGrantedAuthority("ROLE_NOT_EQUAL")))).isFalse();
assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_TEST"))).isTrue(); assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_TEST"))).isTrue();
assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_NOT_EQUAL"))).isFalse(); assertThat(gaSid.equals(new GrantedAuthoritySid("ROLE_NOT_EQUAL"))).isFalse();
} }
@Test @Test
public void testPrincipalSidHashCode() { public void testPrincipalSidHashCode() {
Authentication authentication = new TestingAuthenticationToken("johndoe", Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
"password");
Sid principalSid = new PrincipalSid(authentication); Sid principalSid = new PrincipalSid(authentication);
assertThat(principalSid.hashCode()).isEqualTo("johndoe".hashCode()); assertThat(principalSid.hashCode()).isEqualTo("johndoe".hashCode());
assertThat(principalSid.hashCode()).isEqualTo( assertThat(principalSid.hashCode()).isEqualTo(new PrincipalSid("johndoe").hashCode());
new PrincipalSid("johndoe").hashCode()); assertThat(principalSid.hashCode()).isNotEqualTo(new PrincipalSid("scott").hashCode());
assertThat(principalSid.hashCode()).isNotEqualTo( assertThat(principalSid.hashCode())
new PrincipalSid("scott").hashCode()); .isNotEqualTo(new PrincipalSid(new TestingAuthenticationToken("scott", "password")).hashCode());
assertThat(principalSid.hashCode()).isNotEqualTo(new PrincipalSid(
new TestingAuthenticationToken("scott", "password")).hashCode());
} }
@Test @Test
@ -194,18 +184,15 @@ public class SidTests {
Sid gaSid = new GrantedAuthoritySid(ga); Sid gaSid = new GrantedAuthoritySid(ga);
assertThat(gaSid.hashCode()).isEqualTo("ROLE_TEST".hashCode()); assertThat(gaSid.hashCode()).isEqualTo("ROLE_TEST".hashCode());
assertThat(gaSid.hashCode()).isEqualTo( assertThat(gaSid.hashCode()).isEqualTo(new GrantedAuthoritySid("ROLE_TEST").hashCode());
new GrantedAuthoritySid("ROLE_TEST").hashCode()); assertThat(gaSid.hashCode()).isNotEqualTo(new GrantedAuthoritySid("ROLE_TEST_2").hashCode());
assertThat(gaSid.hashCode()).isNotEqualTo( assertThat(gaSid.hashCode())
new GrantedAuthoritySid("ROLE_TEST_2").hashCode()); .isNotEqualTo(new GrantedAuthoritySid(new SimpleGrantedAuthority("ROLE_TEST_2")).hashCode());
assertThat(gaSid.hashCode()).isNotEqualTo(new GrantedAuthoritySid(
new SimpleGrantedAuthority("ROLE_TEST_2")).hashCode());
} }
@Test @Test
public void testGetters() { public void testGetters() {
Authentication authentication = new TestingAuthenticationToken("johndoe", Authentication authentication = new TestingAuthenticationToken("johndoe", "password");
"password");
PrincipalSid principalSid = new PrincipalSid(authentication); PrincipalSid principalSid = new PrincipalSid(authentication);
GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST"); GrantedAuthority ga = new SimpleGrantedAuthority("ROLE_TEST");
GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga); GrantedAuthoritySid gaSid = new GrantedAuthoritySid(ga);
@ -243,6 +230,7 @@ public class SidTests {
} }
static class CustomAuthenticationToken extends AbstractAuthenticationToken { static class CustomAuthenticationToken extends AbstractAuthenticationToken {
private CustomToken principal; private CustomToken principal;
CustomAuthenticationToken(CustomToken principal, Collection<GrantedAuthority> authorities) { CustomAuthenticationToken(CustomToken principal, Collection<GrantedAuthority> authorities) {
@ -264,9 +252,11 @@ public class SidTests {
public String getName() { public String getName() {
return principal.getName(); return principal.getName();
} }
} }
static class CustomToken { static class CustomToken {
private String name; private String name;
CustomToken(String name) { CustomToken(String name) {
@ -276,5 +266,7 @@ public class SidTests {
String getName() { String getName() {
return name; return name;
} }
} }
} }

View File

@ -50,36 +50,37 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
/** /**
*
* @author Luke Taylor * @author Luke Taylor
* @since 3.0.3 * @since 3.0.3
*/ */
public class AnnotationSecurityAspectTests { public class AnnotationSecurityAspectTests {
private AffirmativeBased adm; private AffirmativeBased adm;
private @Mock AuthenticationManager authman; private @Mock AuthenticationManager authman;
private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "",
"ROLE_A"); private TestingAuthenticationToken anne = new TestingAuthenticationToken("anne", "", "ROLE_A");
// private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "", // private TestingAuthenticationToken bob = new TestingAuthenticationToken("bob", "",
// "ROLE_B"); // "ROLE_B");
private AspectJMethodSecurityInterceptor interceptor; private AspectJMethodSecurityInterceptor interceptor;
private SecuredImpl secured = new SecuredImpl(); private SecuredImpl secured = new SecuredImpl();
private SecuredImplSubclass securedSub = new SecuredImplSubclass(); private SecuredImplSubclass securedSub = new SecuredImplSubclass();
private PrePostSecured prePostSecured = new PrePostSecured(); private PrePostSecured prePostSecured = new PrePostSecured();
@Before @Before
public final void setUp() { public final void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
interceptor = new AspectJMethodSecurityInterceptor(); interceptor = new AspectJMethodSecurityInterceptor();
AccessDecisionVoter[] voters = new AccessDecisionVoter[] { AccessDecisionVoter[] voters = new AccessDecisionVoter[] { new RoleVoter(),
new RoleVoter(), new PreInvocationAuthorizationAdviceVoter(new ExpressionBasedPreInvocationAdvice()) };
new PreInvocationAuthorizationAdviceVoter( adm = new AffirmativeBased(Arrays.<AccessDecisionVoter<? extends Object>>asList(voters));
new ExpressionBasedPreInvocationAdvice()) };
adm = new AffirmativeBased(
Arrays.<AccessDecisionVoter<? extends Object>> asList(voters));
interceptor.setAccessDecisionManager(adm); interceptor.setAccessDecisionManager(adm);
interceptor.setAuthenticationManager(authman); interceptor.setAuthenticationManager(authman);
interceptor interceptor.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource());
.setSecurityMetadataSource(new SecuredAnnotationSecurityMetadataSource());
AnnotationSecurityAspect secAspect = AnnotationSecurityAspect.aspectOf(); AnnotationSecurityAspect secAspect = AnnotationSecurityAspect.aspectOf();
secAspect.setSecurityInterceptor(interceptor); secAspect.setSecurityInterceptor(interceptor);
} }
@ -151,23 +152,25 @@ public class AnnotationSecurityAspectTests {
private void configureForElAnnotations() { private void configureForElAnnotations() {
DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler(); DefaultMethodSecurityExpressionHandler eh = new DefaultMethodSecurityExpressionHandler();
interceptor interceptor.setSecurityMetadataSource(
.setSecurityMetadataSource(new PrePostAnnotationSecurityMetadataSource( new PrePostAnnotationSecurityMetadataSource(new ExpressionBasedAnnotationAttributeFactory(eh)));
new ExpressionBasedAnnotationAttributeFactory(eh)));
interceptor.setAccessDecisionManager(adm); interceptor.setAccessDecisionManager(adm);
AfterInvocationProviderManager aim = new AfterInvocationProviderManager(); AfterInvocationProviderManager aim = new AfterInvocationProviderManager();
aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider( aim.setProviders(Arrays.asList(new PostInvocationAdviceProvider(new ExpressionBasedPostInvocationAdvice(eh))));
new ExpressionBasedPostInvocationAdvice(eh))));
interceptor.setAfterInvocationManager(aim); interceptor.setAfterInvocationManager(aim);
} }
} }
interface SecuredInterface { interface SecuredInterface {
@Secured("ROLE_X") @Secured("ROLE_X")
void securedMethod(); void securedMethod();
} }
class SecuredImpl implements SecuredInterface { class SecuredImpl implements SecuredInterface {
// Not really secured because AspectJ doesn't inherit annotations from interfaces // Not really secured because AspectJ doesn't inherit annotations from interfaces
public void securedMethod() { public void securedMethod() {
} }
@ -188,18 +191,22 @@ class SecuredImpl implements SecuredInterface {
public void publicCallsPrivate() { public void publicCallsPrivate() {
privateMethod(); privateMethod();
} }
} }
class SecuredImplSubclass extends SecuredImpl { class SecuredImplSubclass extends SecuredImpl {
protected void protectedMethod() { protected void protectedMethod() {
} }
public void publicCallsPrivate() { public void publicCallsPrivate() {
super.publicCallsPrivate(); super.publicCallsPrivate();
} }
} }
class PrePostSecured { class PrePostSecured {
@PreAuthorize("denyAll") @PreAuthorize("denyAll")
public void denyAllMethod() { public void denyAllMethod() {
} }
@ -207,8 +214,8 @@ class PrePostSecured {
@PostFilter("filterObject.startsWith('a')") @PostFilter("filterObject.startsWith('a')")
public List<String> postFilterMethod() { public List<String> postFilterMethod() {
ArrayList<String> objects = new ArrayList<>(); ArrayList<String> objects = new ArrayList<>();
objects.addAll(Arrays.asList(new String[] { "apple", "banana", "aubergine", objects.addAll(Arrays.asList(new String[] { "apple", "banana", "aubergine", "orange" }));
"orange" }));
return objects; return objects;
} }
} }

View File

@ -32,4 +32,5 @@ public final class SamlServiceProperties extends ServiceProperties {
super.setArtifactParameter(DEFAULT_SAML_ARTIFACT_PARAMETER); super.setArtifactParameter(DEFAULT_SAML_ARTIFACT_PARAMETER);
super.setServiceParameter(DEFAULT_SAML_SERVICE_PARAMETER); super.setServiceParameter(DEFAULT_SAML_SERVICE_PARAMETER);
} }
} }

View File

@ -65,7 +65,6 @@ public class ServiceProperties implements InitializingBean {
* <pre> * <pre>
* https://www.mycompany.com/application/login/cas * https://www.mycompany.com/application/login/cas
* </pre> * </pre>
*
* @return the URL of the service the user is authenticating to * @return the URL of the service the user is authenticating to
*/ */
public final String getService() { public final String getService() {
@ -81,7 +80,6 @@ public class ServiceProperties implements InitializingBean {
* ticket was generated as a consequence of an explicit login. High security * ticket was generated as a consequence of an explicit login. High security
* applications would probably set this to <code>true</code>. Defaults to * applications would probably set this to <code>true</code>. Defaults to
* <code>false</code>, providing automated single sign on. * <code>false</code>, providing automated single sign on.
*
* @return whether to send the <code>renew</code> parameter to CAS * @return whether to send the <code>renew</code> parameter to CAS
*/ */
public final boolean isSendRenew() { public final boolean isSendRenew() {
@ -103,7 +101,6 @@ public class ServiceProperties implements InitializingBean {
/** /**
* Configures the Request Parameter to look for when attempting to see if a CAS ticket * Configures the Request Parameter to look for when attempting to see if a CAS ticket
* was sent from the server. * was sent from the server.
*
* @param artifactParameter the id to use. Default is "ticket". * @param artifactParameter the id to use. Default is "ticket".
*/ */
public final void setArtifactParameter(final String artifactParameter) { public final void setArtifactParameter(final String artifactParameter) {
@ -113,7 +110,6 @@ public class ServiceProperties implements InitializingBean {
/** /**
* Configures the Request parameter to look for when attempting to send a request to * Configures the Request parameter to look for when attempting to send a request to
* CAS. * CAS.
*
* @return the service parameter to use. Default is "service". * @return the service parameter to use. Default is "service".
*/ */
public final String getServiceParameter() { public final String getServiceParameter() {
@ -132,11 +128,10 @@ public class ServiceProperties implements InitializingBean {
* If true, then any non-null artifact (ticket) should be authenticated. Additionally, * If true, then any non-null artifact (ticket) should be authenticated. Additionally,
* the service will be determined dynamically in order to ensure the service matches * the service will be determined dynamically in order to ensure the service matches
* the expected value for this artifact. * the expected value for this artifact.
*
* @param authenticateAllArtifacts * @param authenticateAllArtifacts
*/ */
public final void setAuthenticateAllArtifacts( public final void setAuthenticateAllArtifacts(final boolean authenticateAllArtifacts) {
final boolean authenticateAllArtifacts) {
this.authenticateAllArtifacts = authenticateAllArtifacts; this.authenticateAllArtifacts = authenticateAllArtifacts;
} }
} }

View File

@ -53,4 +53,5 @@ public final class CasAssertionAuthenticationToken extends AbstractAuthenticatio
public Assertion getAssertion() { public Assertion getAssertion() {
return this.assertion; return this.assertion;
} }
} }

View File

@ -54,8 +54,8 @@ import org.springframework.util.Assert;
* @author Ben Alex * @author Ben Alex
* @author Scott Battaglia * @author Scott Battaglia
*/ */
public class CasAuthenticationProvider implements AuthenticationProvider, public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
InitializingBean, MessageSourceAware {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
@ -67,67 +67,65 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService; private AuthenticationUserDetailsService<CasAssertionAuthenticationToken> authenticationUserDetailsService;
private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker(); private final UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache(); private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
private String key; private String key;
private TicketValidator ticketValidator; private TicketValidator ticketValidator;
private ServiceProperties serviceProperties; private ServiceProperties serviceProperties;
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
// ~ Methods // ~ Methods
// ======================================================================================================== // ========================================================================================================
public void afterPropertiesSet() { public void afterPropertiesSet() {
Assert.notNull(this.authenticationUserDetailsService, Assert.notNull(this.authenticationUserDetailsService, "An authenticationUserDetailsService must be set");
"An authenticationUserDetailsService must be set");
Assert.notNull(this.ticketValidator, "A ticketValidator must be set"); Assert.notNull(this.ticketValidator, "A ticketValidator must be set");
Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set"); Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set");
Assert.hasText( Assert.hasText(this.key,
this.key,
"A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated"); "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated");
Assert.notNull(this.messages, "A message source must be set"); Assert.notNull(this.messages, "A message source must be set");
} }
public Authentication authenticate(Authentication authentication) public Authentication authenticate(Authentication authentication) throws AuthenticationException {
throws AuthenticationException {
if (!supports(authentication.getClass())) { if (!supports(authentication.getClass())) {
return null; return null;
} }
if (authentication instanceof UsernamePasswordAuthenticationToken if (authentication instanceof UsernamePasswordAuthenticationToken
&& (!CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER && (!CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER.equals(authentication.getPrincipal().toString())
.equals(authentication.getPrincipal().toString()) && !CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER && !CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER
.equals(authentication.getPrincipal().toString()))) { .equals(authentication.getPrincipal().toString()))) {
// UsernamePasswordAuthenticationToken not CAS related // UsernamePasswordAuthenticationToken not CAS related
return null; return null;
} }
// If an existing CasAuthenticationToken, just check we created it // If an existing CasAuthenticationToken, just check we created it
if (authentication instanceof CasAuthenticationToken) { if (authentication instanceof CasAuthenticationToken) {
if (this.key.hashCode() == ((CasAuthenticationToken) authentication) if (this.key.hashCode() == ((CasAuthenticationToken) authentication).getKeyHash()) {
.getKeyHash()) {
return authentication; return authentication;
} }
else { else {
throw new BadCredentialsException( throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.incorrectKey",
messages.getMessage("CasAuthenticationProvider.incorrectKey", "The presented CasAuthenticationToken does not contain the expected key"));
"The presented CasAuthenticationToken does not contain the expected key"));
} }
} }
// Ensure credentials are presented // Ensure credentials are presented
if ((authentication.getCredentials() == null) if ((authentication.getCredentials() == null) || "".equals(authentication.getCredentials())) {
|| "".equals(authentication.getCredentials())) { throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.noServiceTicket",
throw new BadCredentialsException(messages.getMessage(
"CasAuthenticationProvider.noServiceTicket",
"Failed to provide a CAS service ticket to validate")); "Failed to provide a CAS service ticket to validate"));
} }
boolean stateless = false; boolean stateless = false;
if (authentication instanceof UsernamePasswordAuthenticationToken if (authentication instanceof UsernamePasswordAuthenticationToken
&& CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication && CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal())) {
.getPrincipal())) {
stateless = true; stateless = true;
} }
@ -135,8 +133,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
if (stateless) { if (stateless) {
// Try to obtain from cache // Try to obtain from cache
result = statelessTicketCache.getByTicketId(authentication.getCredentials() result = statelessTicketCache.getByTicketId(authentication.getCredentials().toString());
.toString());
} }
if (result == null) { if (result == null) {
@ -152,17 +149,14 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
return result; return result;
} }
private CasAuthenticationToken authenticateNow(final Authentication authentication) private CasAuthenticationToken authenticateNow(final Authentication authentication) throws AuthenticationException {
throws AuthenticationException {
try { try {
final Assertion assertion = this.ticketValidator.validate(authentication final Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(),
.getCredentials().toString(), getServiceUrl(authentication)); getServiceUrl(authentication));
final UserDetails userDetails = loadUserByAssertion(assertion); final UserDetails userDetails = loadUserByAssertion(assertion);
userDetailsChecker.check(userDetails); userDetailsChecker.check(userDetails);
return new CasAuthenticationToken(this.key, userDetails, return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(),
authentication.getCredentials(), authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), userDetails, assertion);
authoritiesMapper.mapAuthorities(userDetails.getAuthorities()),
userDetails, assertion);
} }
catch (final TicketValidationException e) { catch (final TicketValidationException e) {
throw new BadCredentialsException(e.getMessage(), e); throw new BadCredentialsException(e.getMessage(), e);
@ -174,15 +168,13 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
* {@link ServiceAuthenticationDetails}, then * {@link ServiceAuthenticationDetails}, then
* {@link ServiceAuthenticationDetails#getServiceUrl()} is used. Otherwise, the * {@link ServiceAuthenticationDetails#getServiceUrl()} is used. Otherwise, the
* {@link ServiceProperties#getService()} is used. * {@link ServiceProperties#getService()} is used.
*
* @param authentication * @param authentication
* @return * @return
*/ */
private String getServiceUrl(Authentication authentication) { private String getServiceUrl(Authentication authentication) {
String serviceUrl; String serviceUrl;
if (authentication.getDetails() instanceof ServiceAuthenticationDetails) { if (authentication.getDetails() instanceof ServiceAuthenticationDetails) {
serviceUrl = ((ServiceAuthenticationDetails) authentication.getDetails()) serviceUrl = ((ServiceAuthenticationDetails) authentication.getDetails()).getServiceUrl();
.getServiceUrl();
} }
else if (serviceProperties == null) { else if (serviceProperties == null) {
throw new IllegalStateException( throw new IllegalStateException(
@ -205,13 +197,11 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
* Template method for retrieving the UserDetails based on the assertion. Default is * Template method for retrieving the UserDetails based on the assertion. Default is
* to call configured userDetailsService and pass the username. Deployers can override * to call configured userDetailsService and pass the username. Deployers can override
* this method and retrieve the user based on any criteria they desire. * this method and retrieve the user based on any criteria they desire.
*
* @param assertion The CAS Assertion. * @param assertion The CAS Assertion.
* @return the UserDetails. * @return the UserDetails.
*/ */
protected UserDetails loadUserByAssertion(final Assertion assertion) { protected UserDetails loadUserByAssertion(final Assertion assertion) {
final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken( final CasAssertionAuthenticationToken token = new CasAssertionAuthenticationToken(assertion, "");
assertion, "");
return this.authenticationUserDetailsService.loadUserDetails(token); return this.authenticationUserDetailsService.loadUserDetails(token);
} }
@ -220,8 +210,7 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
* Sets the UserDetailsService to use. This is a convenience method to invoke * Sets the UserDetailsService to use. This is a convenience method to invoke
*/ */
public void setUserDetailsService(final UserDetailsService userDetailsService) { public void setUserDetailsService(final UserDetailsService userDetailsService) {
this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper( this.authenticationUserDetailsService = new UserDetailsByNameServiceWrapper(userDetailsService);
userDetailsService);
} }
public void setAuthenticationUserDetailsService( public void setAuthenticationUserDetailsService(
@ -266,10 +255,9 @@ public class CasAuthenticationProvider implements AuthenticationProvider,
} }
public boolean supports(final Class<?> authentication) { public boolean supports(final Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication))
.isAssignableFrom(authentication))
|| (CasAuthenticationToken.class.isAssignableFrom(authentication)) || (CasAuthenticationToken.class.isAssignableFrom(authentication))
|| (CasAssertionAuthenticationToken.class || (CasAssertionAuthenticationToken.class.isAssignableFrom(authentication));
.isAssignableFrom(authentication));
} }
} }

View File

@ -32,17 +32,20 @@ import org.springframework.util.Assert;
* @author Ben Alex * @author Ben Alex
* @author Scott Battaglia * @author Scott Battaglia
*/ */
public class CasAuthenticationToken extends AbstractAuthenticationToken implements public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
private final Object credentials; private final Object credentials;
private final Object principal; private final Object principal;
private final UserDetails userDetails; private final UserDetails userDetails;
private final int keyHash; private final int keyHash;
private final Assertion assertion; private final Assertion assertion;
// ~ Constructors // ~ Constructors
@ -50,60 +53,53 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
/** /**
* Constructor. * Constructor.
* * @param key to identify if this object made by a given
* @param key to identify if this object made by a given * {@link CasAuthenticationProvider}
* {@link CasAuthenticationProvider} * @param principal typically the UserDetails object (cannot be <code>null</code>)
* @param principal typically the UserDetails object (cannot be <code>null</code>)
* @param credentials the service/proxy ticket ID from CAS (cannot be * @param credentials the service/proxy ticket ID from CAS (cannot be
* <code>null</code>) * <code>null</code>)
* @param authorities the authorities granted to the user (from the * @param authorities the authorities granted to the user (from the
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
* be <code>null</code>) * be <code>null</code>)
* @param userDetails the user details (from the * @param userDetails the user details (from the
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
* be <code>null</code>) * be <code>null</code>)
* @param assertion the assertion returned from the CAS servers. It contains the * @param assertion the assertion returned from the CAS servers. It contains the
* principal and how to obtain a proxy ticket for the user. * principal and how to obtain a proxy ticket for the user.
* @throws IllegalArgumentException if a <code>null</code> was passed * @throws IllegalArgumentException if a <code>null</code> was passed
*/ */
public CasAuthenticationToken(final String key, final Object principal, public CasAuthenticationToken(final String key, final Object principal, final Object credentials,
final Object credentials, final Collection<? extends GrantedAuthority> authorities, final UserDetails userDetails,
final Collection<? extends GrantedAuthority> authorities, final Assertion assertion) {
final UserDetails userDetails, final Assertion assertion) {
this(extractKeyHash(key), principal, credentials, authorities, userDetails, assertion); this(extractKeyHash(key), principal, credentials, authorities, userDetails, assertion);
} }
/** /**
* Private constructor for Jackson Deserialization support * Private constructor for Jackson Deserialization support
* * @param keyHash hashCode of provided key to identify if this object made by a given
* @param keyHash hashCode of provided key to identify if this object made by a given * {@link CasAuthenticationProvider}
* {@link CasAuthenticationProvider} * @param principal typically the UserDetails object (cannot be <code>null</code>)
* @param principal typically the UserDetails object (cannot be <code>null</code>)
* @param credentials the service/proxy ticket ID from CAS (cannot be * @param credentials the service/proxy ticket ID from CAS (cannot be
* <code>null</code>) * <code>null</code>)
* @param authorities the authorities granted to the user (from the * @param authorities the authorities granted to the user (from the
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
* be <code>null</code>) * be <code>null</code>)
* @param userDetails the user details (from the * @param userDetails the user details (from the
* {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot * {@link org.springframework.security.core.userdetails.UserDetailsService}) (cannot
* be <code>null</code>) * be <code>null</code>)
* @param assertion the assertion returned from the CAS servers. It contains the * @param assertion the assertion returned from the CAS servers. It contains the
* principal and how to obtain a proxy ticket for the user. * principal and how to obtain a proxy ticket for the user.
* @throws IllegalArgumentException if a <code>null</code> was passed * @throws IllegalArgumentException if a <code>null</code> was passed
* @since 4.2 * @since 4.2
*/ */
private CasAuthenticationToken(final Integer keyHash, final Object principal, private CasAuthenticationToken(final Integer keyHash, final Object principal, final Object credentials,
final Object credentials, final Collection<? extends GrantedAuthority> authorities, final UserDetails userDetails,
final Collection<? extends GrantedAuthority> authorities, final Assertion assertion) {
final UserDetails userDetails, final Assertion assertion) {
super(authorities); super(authorities);
if ((principal == null) if ((principal == null) || "".equals(principal) || (credentials == null) || "".equals(credentials)
|| "".equals(principal) || (credentials == null) || (authorities == null) || (userDetails == null) || (assertion == null)) {
|| "".equals(credentials) || (authorities == null) throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
|| (userDetails == null) || (assertion == null)) {
throw new IllegalArgumentException(
"Cannot pass null or empty values to constructor");
} }
this.keyHash = keyHash; this.keyHash = keyHash;
@ -187,4 +183,5 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
return (sb.toString()); return (sb.toString());
} }
} }

View File

@ -25,12 +25,13 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Caches tickets using a Spring IoC defined <a * Caches tickets using a Spring IoC defined
* href="https://www.ehcache.org/">EHCACHE</a>. * <a href="https://www.ehcache.org/">EHCACHE</a>.
* *
* @author Ben Alex * @author Ben Alex
*/ */
public class EhCacheBasedTicketCache implements StatelessTicketCache, InitializingBean { public class EhCacheBasedTicketCache implements StatelessTicketCache, InitializingBean {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
@ -52,8 +53,7 @@ public class EhCacheBasedTicketCache implements StatelessTicketCache, Initializi
final Element element = cache.get(serviceTicket); final Element element = cache.get(serviceTicket);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Cache hit: " + (element != null) + "; service ticket: " logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket);
+ serviceTicket);
} }
return element == null ? null : (CasAuthenticationToken) element.getValue(); return element == null ? null : (CasAuthenticationToken) element.getValue();
@ -88,4 +88,5 @@ public class EhCacheBasedTicketCache implements StatelessTicketCache, Initializi
public void setCache(final Ehcache cache) { public void setCache(final Ehcache cache) {
this.cache = cache; this.cache = cache;
} }
} }

View File

@ -24,7 +24,6 @@ package org.springframework.security.cas.authentication;
* are not using the stateless session management. * are not using the stateless session management.
* *
* @author Scott Battaglia * @author Scott Battaglia
*
* @see CasAuthenticationProvider * @see CasAuthenticationProvider
*/ */
public final class NullStatelessTicketCache implements StatelessTicketCache { public final class NullStatelessTicketCache implements StatelessTicketCache {
@ -56,4 +55,5 @@ public final class NullStatelessTicketCache implements StatelessTicketCache {
public void removeTicketFromCache(final String serviceTicket) { public void removeTicketFromCache(final String serviceTicket) {
// nothing to do // nothing to do
} }
} }

View File

@ -28,11 +28,11 @@ import org.springframework.util.Assert;
* *
*/ */
public class SpringCacheBasedTicketCache implements StatelessTicketCache { public class SpringCacheBasedTicketCache implements StatelessTicketCache {
// ~ Static fields/initializers // ~ Static fields/initializers
// ===================================================================================== // =====================================================================================
private static final Log logger = LogFactory private static final Log logger = LogFactory.getLog(SpringCacheBasedTicketCache.class);
.getLog(SpringCacheBasedTicketCache.class);
// ~ Instance fields // ~ Instance fields
// ================================================================================================ // ================================================================================================
@ -51,12 +51,10 @@ public class SpringCacheBasedTicketCache implements StatelessTicketCache {
// ======================================================================================================== // ========================================================================================================
public CasAuthenticationToken getByTicketId(final String serviceTicket) { public CasAuthenticationToken getByTicketId(final String serviceTicket) {
final Cache.ValueWrapper element = serviceTicket != null ? cache final Cache.ValueWrapper element = serviceTicket != null ? cache.get(serviceTicket) : null;
.get(serviceTicket) : null;
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Cache hit: " + (element != null) + "; service ticket: " logger.debug("Cache hit: " + (element != null) + "; service ticket: " + serviceTicket);
+ serviceTicket);
} }
return element == null ? null : (CasAuthenticationToken) element.get(); return element == null ? null : (CasAuthenticationToken) element.get();
@ -83,4 +81,5 @@ public class SpringCacheBasedTicketCache implements StatelessTicketCache {
public void removeTicketFromCache(final String serviceTicket) { public void removeTicketFromCache(final String serviceTicket) {
cache.evict(serviceTicket); cache.evict(serviceTicket);
} }
} }

View File

@ -59,6 +59,7 @@ package org.springframework.security.cas.authentication;
* @author Ben Alex * @author Ben Alex
*/ */
public interface StatelessTicketCache { public interface StatelessTicketCache {
// ~ Methods ================================================================ // ~ Methods ================================================================
/** /**
@ -68,7 +69,6 @@ public interface StatelessTicketCache {
* <P> * <P>
* If not found, returns a <code>null</code><code>CasAuthenticationToken</code>. * If not found, returns a <code>null</code><code>CasAuthenticationToken</code>.
* </p> * </p>
*
* @return the fully populated authentication token * @return the fully populated authentication token
*/ */
CasAuthenticationToken getByTicketId(String serviceTicket); CasAuthenticationToken getByTicketId(String serviceTicket);
@ -80,7 +80,6 @@ public interface StatelessTicketCache {
* The {@link CasAuthenticationToken#getCredentials()} method is used to retrieve the * The {@link CasAuthenticationToken#getCredentials()} method is used to retrieve the
* service ticket number. * service ticket number.
* </p> * </p>
*
* @param token to be added to the cache * @param token to be added to the cache
*/ */
void putTicketInCache(CasAuthenticationToken token); void putTicketInCache(CasAuthenticationToken token);
@ -91,10 +90,9 @@ public interface StatelessTicketCache {
* *
* <P> * <P>
* Implementations should use {@link CasAuthenticationToken#getCredentials()} to * Implementations should use {@link CasAuthenticationToken#getCredentials()} to
* obtain the ticket and then delegate to the * obtain the ticket and then delegate to the {@link #removeTicketFromCache(String)}
* {@link #removeTicketFromCache(String)} method. * method.
* </p> * </p>
*
* @param token to be removed * @param token to be removed
*/ */
void removeTicketFromCache(CasAuthenticationToken token); void removeTicketFromCache(CasAuthenticationToken token);
@ -107,8 +105,8 @@ public interface StatelessTicketCache {
* This is in case applications wish to provide a session termination capability for * This is in case applications wish to provide a session termination capability for
* their stateless clients. * their stateless clients.
* </p> * </p>
*
* @param serviceTicket to be removed * @param serviceTicket to be removed
*/ */
void removeTicketFromCache(String serviceTicket); void removeTicketFromCache(String serviceTicket);
} }

Some files were not shown because too many files have changed in this diff Show More