Added possibility create custom Sid
This commit is contained in:
parent
fa9e7999da
commit
f20219d541
|
@ -87,7 +87,7 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
// Check if authorized by virtue of ACL ownership
|
// Check if authorized by virtue of ACL ownership
|
||||||
Sid currentUser = new PrincipalSid(authentication);
|
Sid currentUser = createCurrentUser(authentication);
|
||||||
|
|
||||||
if (currentUser.equals(acl.getOwner())
|
if (currentUser.equals(acl.getOwner())
|
||||||
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
|
&& ((changeType == CHANGE_GENERAL) || (changeType == CHANGE_OWNERSHIP))) {
|
||||||
|
@ -123,6 +123,17 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {
|
||||||
"Principal does not have required ACL permissions to perform requested operation");
|
"Principal does not have required ACL permissions to perform requested operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a principal-like sid from the authentication information.
|
||||||
|
*
|
||||||
|
* @param authentication the authentication information that can provide principal and thus the sid's id will be
|
||||||
|
* dependant on the value inside
|
||||||
|
* @return a sid with the ID taken from the authentication information
|
||||||
|
*/
|
||||||
|
protected Sid createCurrentUser(Authentication authentication) {
|
||||||
|
return new PrincipalSid(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
|
public void setSidRetrievalStrategy(SidRetrievalStrategy sidRetrievalStrategy) {
|
||||||
Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required");
|
Assert.notNull(sidRetrievalStrategy, "SidRetrievalStrategy required");
|
||||||
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
this.sidRetrievalStrategy = sidRetrievalStrategy;
|
||||||
|
|
|
@ -74,7 +74,7 @@ import org.springframework.util.Assert;
|
||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public final class BasicLookupStrategy implements LookupStrategy {
|
public class BasicLookupStrategy implements LookupStrategy {
|
||||||
|
|
||||||
public final static String DEFAULT_SELECT_CLAUSE = "select acl_object_identity.object_id_identity, "
|
public final static String DEFAULT_SELECT_CLAUSE = "select acl_object_identity.object_id_identity, "
|
||||||
+ "acl_entry.ace_order, "
|
+ "acl_entry.ace_order, "
|
||||||
|
@ -256,7 +256,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||||
* should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used
|
* should not throw {@link NotFoundException}, as a chain of {@link LookupStrategy}s may be used
|
||||||
* to automatically create entries if required)
|
* to automatically create entries if required)
|
||||||
*/
|
*/
|
||||||
public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids) {
|
public final Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, 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");
|
||||||
|
|
||||||
|
@ -428,17 +428,33 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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
|
||||||
|
* @return the instance of Sid with the {@code sidName} as an identifier
|
||||||
|
*/
|
||||||
|
protected Sid createSid(boolean isPrincipal, String sid) {
|
||||||
|
if (isPrincipal) {
|
||||||
|
return new PrincipalSid(sid);
|
||||||
|
} else {
|
||||||
|
return new GrantedAuthoritySid(sid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@code PermissionFactory} instance which will be used to convert loaded permission
|
* Sets the {@code PermissionFactory} instance which will be used to convert loaded permission
|
||||||
* data values to {@code Permission}s. A {@code DefaultPermissionFactory} will be used by default.
|
* data values to {@code Permission}s. A {@code DefaultPermissionFactory} will be used by default.
|
||||||
*
|
*
|
||||||
* @param permissionFactory
|
* @param permissionFactory
|
||||||
*/
|
*/
|
||||||
public void setPermissionFactory(PermissionFactory permissionFactory) {
|
public final void setPermissionFactory(PermissionFactory permissionFactory) {
|
||||||
this.permissionFactory = permissionFactory;
|
this.permissionFactory = permissionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBatchSize(int batchSize) {
|
public final void setBatchSize(int batchSize) {
|
||||||
this.batchSize = batchSize;
|
this.batchSize = batchSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,28 +464,28 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||||
*
|
*
|
||||||
* @param selectClause the select clause, which defaults to {@link #DEFAULT_SELECT_CLAUSE}.
|
* @param selectClause the select clause, which defaults to {@link #DEFAULT_SELECT_CLAUSE}.
|
||||||
*/
|
*/
|
||||||
public void setSelectClause(String selectClause) {
|
public final void setSelectClause(String selectClause) {
|
||||||
this.selectClause = selectClause;
|
this.selectClause = selectClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SQL for the where clause used in the <tt>lookupPrimaryKey</tt> method.
|
* The SQL for the where clause used in the <tt>lookupPrimaryKey</tt> method.
|
||||||
*/
|
*/
|
||||||
public void setLookupPrimaryKeysWhereClause(String lookupPrimaryKeysWhereClause) {
|
public final void setLookupPrimaryKeysWhereClause(String lookupPrimaryKeysWhereClause) {
|
||||||
this.lookupPrimaryKeysWhereClause = lookupPrimaryKeysWhereClause;
|
this.lookupPrimaryKeysWhereClause = lookupPrimaryKeysWhereClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 void setLookupObjectIdentitiesWhereClause(String lookupObjectIdentitiesWhereClause) {
|
public final void setLookupObjectIdentitiesWhereClause(String lookupObjectIdentitiesWhereClause) {
|
||||||
this.lookupObjectIdentitiesWhereClause = lookupObjectIdentitiesWhereClause;
|
this.lookupObjectIdentitiesWhereClause = lookupObjectIdentitiesWhereClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SQL for the "order by" clause used in both queries.
|
* The SQL for the "order by" clause used in both queries.
|
||||||
*/
|
*/
|
||||||
public void setOrderByClause(String orderByClause) {
|
public final void setOrderByClause(String orderByClause) {
|
||||||
this.orderByClause = orderByClause;
|
this.orderByClause = orderByClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,13 +572,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean entriesInheriting = rs.getBoolean("entries_inheriting");
|
boolean entriesInheriting = rs.getBoolean("entries_inheriting");
|
||||||
Sid owner;
|
Sid owner = createSid(rs.getBoolean("acl_principal"), rs.getString("acl_sid"));
|
||||||
|
|
||||||
if (rs.getBoolean("acl_principal")) {
|
|
||||||
owner = new PrincipalSid(rs.getString("acl_sid"));
|
|
||||||
} else {
|
|
||||||
owner = new GrantedAuthoritySid(rs.getString("acl_sid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, grantingStrategy, parentAcl, null,
|
acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, grantingStrategy, parentAcl, null,
|
||||||
entriesInheriting, owner);
|
entriesInheriting, owner);
|
||||||
|
@ -574,13 +584,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
|
||||||
// It is permissible to have no ACEs in an ACL (which is detected by a null ACE_SID)
|
// It is permissible to have no ACEs in an ACL (which is detected by a null ACE_SID)
|
||||||
if (rs.getString("ace_sid") != null) {
|
if (rs.getString("ace_sid") != null) {
|
||||||
Long aceId = new Long(rs.getLong("ace_id"));
|
Long aceId = new Long(rs.getLong("ace_id"));
|
||||||
Sid recipient;
|
Sid recipient = createSid(rs.getBoolean("ace_principal"), rs.getString("ace_sid"));
|
||||||
|
|
||||||
if (rs.getBoolean("ace_principal")) {
|
|
||||||
recipient = new PrincipalSid(rs.getString("ace_sid"));
|
|
||||||
} else {
|
|
||||||
recipient = new GrantedAuthoritySid(rs.getString("ace_sid"));
|
|
||||||
}
|
|
||||||
|
|
||||||
int mask = rs.getInt("mask");
|
int mask = rs.getInt("mask");
|
||||||
Permission permission = permissionFactory.buildFromMask(mask);
|
Permission permission = permissionFactory.buildFromMask(mask);
|
||||||
|
|
|
@ -209,6 +209,19 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
|
||||||
throw new IllegalArgumentException("Unsupported implementation of Sid");
|
throw new IllegalArgumentException("Unsupported implementation of Sid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return createOrRetrieveSidPrimaryKey(sidName, sidIsPrincipal, allowCreate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the primary key from acl_sid, creating a new row if needed and the allowCreate property is
|
||||||
|
* true.
|
||||||
|
* @param sidName name of Sid to find or to create
|
||||||
|
* @param sidIsPrincipal whether it's a user or granted authority like role
|
||||||
|
* @param allowCreate true if creation is permitted if not found
|
||||||
|
* @return the primary key or null if not found
|
||||||
|
*/
|
||||||
|
protected Long createOrRetrieveSidPrimaryKey(String sidName, boolean sidIsPrincipal, boolean allowCreate) {
|
||||||
|
|
||||||
List<Long> sidIds = jdbcTemplate.queryForList(selectSidPrimaryKey,
|
List<Long> sidIds = jdbcTemplate.queryForList(selectSidPrimaryKey,
|
||||||
new Object[] {Boolean.valueOf(sidIsPrincipal), sidName}, Long.class);
|
new Object[] {Boolean.valueOf(sidIsPrincipal), sidName}, Long.class);
|
||||||
|
|
||||||
|
|
|
@ -9,15 +9,7 @@ import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
|
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
|
||||||
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
|
import org.springframework.security.acls.domain.*;
|
||||||
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
|
|
||||||
import org.springframework.security.acls.domain.BasePermission;
|
|
||||||
import org.springframework.security.acls.domain.ConsoleAuditLogger;
|
|
||||||
import org.springframework.security.acls.domain.DefaultPermissionFactory;
|
|
||||||
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
|
|
||||||
import org.springframework.security.acls.domain.EhCacheBasedAclCache;
|
|
||||||
import org.springframework.security.acls.domain.ObjectIdentityImpl;
|
|
||||||
import org.springframework.security.acls.domain.PrincipalSid;
|
|
||||||
import org.springframework.security.acls.model.Acl;
|
import org.springframework.security.acls.model.Acl;
|
||||||
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
import org.springframework.security.acls.model.AuditableAccessControlEntry;
|
||||||
import org.springframework.security.acls.model.MutableAcl;
|
import org.springframework.security.acls.model.MutableAcl;
|
||||||
|
@ -301,4 +293,20 @@ public class BasicLookupStrategyTests {
|
||||||
strategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
strategy.readAclsById(Arrays.asList(oid), Arrays.asList(BEN_SID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePrincipalSid() {
|
||||||
|
Sid result = strategy.createSid(true, "sid");
|
||||||
|
|
||||||
|
Assert.assertEquals(PrincipalSid.class, result.getClass());
|
||||||
|
Assert.assertEquals("sid", ((PrincipalSid)result).getPrincipal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateGrantedAuthority() {
|
||||||
|
Sid result = strategy.createSid(false, "sid");
|
||||||
|
|
||||||
|
Assert.assertEquals(GrantedAuthoritySid.class, result.getClass());
|
||||||
|
Assert.assertEquals("sid", ((GrantedAuthoritySid)result).getGrantedAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package org.springframework.security.acls.jdbc;
|
package org.springframework.security.acls.jdbc;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -43,6 +44,7 @@ import org.springframework.security.acls.model.NotFoundException;
|
||||||
import org.springframework.security.acls.model.ObjectIdentity;
|
import org.springframework.security.acls.model.ObjectIdentity;
|
||||||
import org.springframework.security.acls.model.Permission;
|
import org.springframework.security.acls.model.Permission;
|
||||||
import org.springframework.security.acls.model.Sid;
|
import org.springframework.security.acls.model.Sid;
|
||||||
|
import org.springframework.security.acls.sid.CustomSid;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
@ -489,6 +491,43 @@ public class JdbcMutableAclServiceTests extends AbstractTransactionalJUnit4Sprin
|
||||||
assertTrue(topParent.isGranted(Arrays.asList(cm), Arrays.asList(benSid), true));
|
assertTrue(topParent.isGranted(Arrays.asList(cm), Arrays.asList(benSid), true));
|
||||||
|
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
public void testProcessingCustomSid() {
|
||||||
|
CustomJdbcMutableAclService customJdbcMutableAclService = spy(new CustomJdbcMutableAclService(dataSource,
|
||||||
|
lookupStrategy, aclCache));
|
||||||
|
CustomSid customSid = new CustomSid("Custom sid");
|
||||||
|
when(customJdbcMutableAclService.createOrRetrieveSidPrimaryKey("Custom sid", false, false)).thenReturn(1L);
|
||||||
|
|
||||||
|
Long result = customJdbcMutableAclService.createOrRetrieveSidPrimaryKey(customSid, false);
|
||||||
|
|
||||||
|
assertEquals(result, new Long(1L));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class needed to show how to extend {@link JdbcMutableAclService} for processing
|
||||||
|
* custom {@link Sid} implementations
|
||||||
|
*/
|
||||||
|
private class CustomJdbcMutableAclService extends JdbcMutableAclService {
|
||||||
|
|
||||||
|
private CustomJdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
|
||||||
|
super(dataSource, lookupStrategy, aclCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Long createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
|
||||||
|
String sidName;
|
||||||
|
boolean isPrincipal = false;
|
||||||
|
if (sid instanceof CustomSid) {
|
||||||
|
sidName = ((CustomSid)sid).getSid();
|
||||||
|
} else if (sid instanceof GrantedAuthoritySid) {
|
||||||
|
sidName = ((GrantedAuthoritySid)sid).getGrantedAuthority();
|
||||||
|
} else {
|
||||||
|
sidName = ((PrincipalSid)sid).getPrincipal();
|
||||||
|
isPrincipal = true;
|
||||||
|
}
|
||||||
|
return createOrRetrieveSidPrimaryKey(sidName, isPrincipal, allowCreate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.springframework.security.acls.sid;
|
||||||
|
|
||||||
|
import org.springframework.security.acls.model.Sid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is example of custom {@link Sid} implementation
|
||||||
|
* @author Mikhail Stryzhonok
|
||||||
|
*/
|
||||||
|
public class CustomSid implements Sid {
|
||||||
|
|
||||||
|
private String sid;
|
||||||
|
|
||||||
|
public CustomSid(String sid) {
|
||||||
|
this.sid = sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSid() {
|
||||||
|
return sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSid(String sid) {
|
||||||
|
this.sid = sid;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue