SEC-1023: PermissionEvaluator based on the Acl module.
This commit is contained in:
parent
a207acf7cb
commit
1c3b576d91
|
@ -0,0 +1,115 @@
|
|||
package org.springframework.security.acls;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.acls.domain.BasePermission;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentity;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategy;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategyImpl;
|
||||
import org.springframework.security.acls.sid.Sid;
|
||||
import org.springframework.security.acls.sid.SidRetrievalStrategy;
|
||||
import org.springframework.security.acls.sid.SidRetrievalStrategyImpl;
|
||||
import org.springframework.security.expression.PermissionEvaluator;
|
||||
|
||||
/**
|
||||
* Used by Spring Security's expression-based access control implementation to evaluate permissions for a particular
|
||||
* object using the ACL module. Similar in behaviour to
|
||||
* {@link org.springframework.security.vote.AclEntryVoter AclEntryVoter}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
*/
|
||||
public class AclPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private AclService aclService;
|
||||
private ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy = new ObjectIdentityRetrievalStrategyImpl();
|
||||
private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();
|
||||
|
||||
public AclPermissionEvaluator(AclService aclService) {
|
||||
this.aclService = aclService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the user has the given permission(s) on the domain object using the ACL
|
||||
* configuration. If the domain object is null, returns false (this can always be overridden using a null
|
||||
* check in the expression itself).
|
||||
*/
|
||||
public boolean hasPermission(Authentication authentication, Object domainObject, Object permission) {
|
||||
if (domainObject == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectIdentity objectIdentity = objectIdentityRetrievalStrategy.getObjectIdentity(domainObject);
|
||||
|
||||
// Obtain the SIDs applicable to the principal
|
||||
Sid[] sids = sidRetrievalStrategy.getSids(authentication);
|
||||
Permission[] requiredPermission = resolvePermission(permission);
|
||||
|
||||
try {
|
||||
// Lookup only ACLs for SIDs we're interested in
|
||||
Acl acl = aclService.readAclById(objectIdentity, sids);
|
||||
|
||||
if (acl.isGranted(requiredPermission, sids, false)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Access is granted");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Returning false - ACLs returned, but insufficient permissions for this principal");
|
||||
}
|
||||
|
||||
} catch (NotFoundException nfe) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Returning false - no ACLs apply for this principal");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add permission resolver/PermissionFactory rewrite
|
||||
Permission[] resolvePermission(Object permission) {
|
||||
if (permission instanceof Integer) {
|
||||
return new Permission[] {BasePermission.buildFromMask(((Integer)permission).intValue())};
|
||||
}
|
||||
|
||||
if (permission instanceof Permission) {
|
||||
return new Permission[] {(Permission)permission};
|
||||
}
|
||||
|
||||
if (permission instanceof Permission[]) {
|
||||
return (Permission[]) permission;
|
||||
}
|
||||
|
||||
if (permission instanceof String) {
|
||||
String permString = (String)permission;
|
||||
Permission p = BasePermission.buildFromName(permString);
|
||||
|
||||
if (p == null) {
|
||||
p = BasePermission.buildFromName(permString.toUpperCase());
|
||||
}
|
||||
|
||||
if (p != null) {
|
||||
return new Permission[] {p};
|
||||
}
|
||||
|
||||
}
|
||||
throw new IllegalArgumentException("unsupported permission: " + permission);
|
||||
}
|
||||
|
||||
public void setObjectIdentityRetrievalStrategy(ObjectIdentityRetrievalStrategy objectIdentityRetrievalStrategy) {
|
||||
this.objectIdentityRetrievalStrategy = objectIdentityRetrievalStrategy;
|
||||
}
|
||||
|
||||
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
|
||||
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.springframework.security.acls;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.jmock.integration.junit4.JUnit4Mockery;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.Authentication;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentity;
|
||||
import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategy;
|
||||
import org.springframework.security.acls.sid.Sid;
|
||||
import org.springframework.security.acls.sid.SidRetrievalStrategy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @since 2.5
|
||||
*/
|
||||
public class AclPermissionEvaluatorTests {
|
||||
Mockery jmock = new JUnit4Mockery();
|
||||
Authentication user;
|
||||
private AclService service;
|
||||
private ObjectIdentityRetrievalStrategy oidStrategy;
|
||||
private SidRetrievalStrategy sidStrategy;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
user = jmock.mock(Authentication.class);
|
||||
service = jmock.mock(AclService.class);
|
||||
oidStrategy = jmock.mock(ObjectIdentityRetrievalStrategy.class);
|
||||
sidStrategy = jmock.mock(SidRetrievalStrategy.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasPermissionReturnsTrueIfAclGrantsPermission() throws Exception {
|
||||
AclPermissionEvaluator pe = new AclPermissionEvaluator(service);
|
||||
final Acl acl = jmock.mock(Acl.class);
|
||||
pe.setObjectIdentityRetrievalStrategy(oidStrategy);
|
||||
pe.setSidRetrievalStrategy(sidStrategy);
|
||||
|
||||
jmock.checking(new Expectations() {{
|
||||
ignoring(user);
|
||||
ignoring(oidStrategy);
|
||||
ignoring(sidStrategy);
|
||||
oneOf(service).readAclById(with(any(ObjectIdentity.class)), with(any(Sid[].class)));
|
||||
will(returnValue(acl));
|
||||
oneOf(acl).isGranted(with(any(Permission[].class)), with(any(Sid[].class)), with(equal(false)));
|
||||
will(returnValue(true));
|
||||
}});
|
||||
|
||||
assertTrue(pe.hasPermission(user, new Object(), "read"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue