1
0
mirror of synced 2026-08-07 02:38:47 +00:00

SEC-593: Added PermissionCacheOptimizer strategy interface and implementation in Acl module.

This is used by DefaultMethodSecurityExpressionHandler to allow permissions to be cached before repeatedly evaluating an expression for a collection of domain objects.
This commit is contained in:
Luke Taylor
2010-02-16 23:43:42 +00:00
parent 1474e73b11
commit b37d2ed978
6 changed files with 131 additions and 10 deletions
@@ -0,0 +1,62 @@
package org.springframework.security.acls;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.PermissionCacheOptimizer;
import org.springframework.security.acls.domain.ObjectIdentityRetrievalStrategyImpl;
import org.springframework.security.acls.domain.SidRetrievalStrategyImpl;
import org.springframework.security.acls.model.AclService;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.ObjectIdentityRetrievalStrategy;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.acls.model.SidRetrievalStrategy;
import org.springframework.security.core.Authentication;
/**
* Batch loads ACLs for collections of objects to allow optimised filtering.
*
* @author Luke Taylor
* @since 3.1
*/
public class AclPermissionCacheOptimizer implements PermissionCacheOptimizer {
private final Log logger = LogFactory.getLog(getClass());
private final AclService aclService;
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
private ObjectIdentityRetrievalStrategy oidRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
public AclPermissionCacheOptimizer(AclService aclService) {
this.aclService = aclService;
}
public void cachePermissionsFor(Authentication authentication, Collection<?> objects) {
List<ObjectIdentity> oidsToCache = new ArrayList<ObjectIdentity>(objects.size());
for (Object domainObject : objects) {
if (domainObject == null) {
continue;
}
ObjectIdentity oid = oidRetrievalStrategy.getObjectIdentity(domainObject);
oidsToCache.add(oid);
}
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
if (logger.isDebugEnabled()) {
logger.debug("Eagerly loading Acls for " + oidsToCache.size() + " objects");
}
aclService.readAclsById(oidsToCache, sids);
}
public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
this.oidRetrievalStrategy = objectIdentityRetrievalStrategy;
}
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
this.sidRetrievalStrategy = sidRetrievalStrategy;
}
}
@@ -70,24 +70,30 @@ public class AclPermissionEvaluator implements PermissionEvaluator {
List<Sid> sids = sidRetrievalStrategy.getSids(authentication);
List<Permission> requiredPermission = resolvePermission(permission);
final boolean debug = logger.isDebugEnabled();
if (debug) {
logger.debug("Checking permission '" + permission + "' for object '" + oid + "'");
}
try {
// Lookup only ACLs for SIDs we're interested in
Acl acl = aclService.readAclById(oid, sids);
if (acl.isGranted(requiredPermission, sids, false)) {
if (logger.isDebugEnabled()) {
if (debug) {
logger.debug("Access is granted");
}
return true;
}
if (logger.isDebugEnabled()) {
if (debug) {
logger.debug("Returning false - ACLs returned, but insufficient permissions for this principal");
}
} catch (NotFoundException nfe) {
if (logger.isDebugEnabled()) {
if (debug) {
logger.debug("Returning false - no ACLs apply for this principal");
}
}