To get starting using Spring Security's ACL capability, you will need to store your
ACL information somewhere. This necessitates the instantiation of a
DataSource
using Spring. The DataSource
is then
injected into a JdbcMutableAclService
and
BasicLookupStrategy
instance. The latter provides
high-performance ACL retrieval capabilities, and the former provides mutator
capabilities. Refer to one of the samples that ship with Spring Security for an example
configuration. You'll also need to populate the database with the four ACL-specific
tables listed in the last section (refer to the ACL samples for the appropriate SQL
statements).
Once you've created the required schema and instantiated
JdbcMutableAclService
, you'll next need to ensure your domain
model supports interoperability with the Spring Security ACL package. Hopefully
ObjectIdentityImpl
will prove sufficient, as it provides a large
number of ways in which it can be used. Most people will have domain objects that
contain a public Serializable getId()
method. If the return type is
long, or compatible with long (eg an int), you will find you need not give further
consideration to ObjectIdentity
issues. Many parts of the ACL module
rely on long identifiers. If you're not using long (or an int, byte etc), there is a
very good chance you'll need to reimplement a number of classes. We do not intend to
support non-long identifiers in Spring Security's ACL module, as longs are already
compatible with all database sequences, the most common identifier data type, and are of
sufficient length to accommodate all common usage scenarios.
The following fragment of code shows how to create an Acl
, or
modify an existing
Acl
:
// Prepare the information we'd like in our access control entry (ACE) ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44)); Sid sid = new PrincipalSid("Samantha"); Permission p = BasePermission.ADMINISTRATION; // Create or update the relevant ACL MutableAcl acl = null; try { acl = (MutableAcl) aclService.readAclById(oi); } catch (NotFoundException nfe) { acl = aclService.createAcl(oi); } // Now grant some permissions via an access control entry (ACE) acl.insertAce(acl.getEntries().length, p, sid, true); aclService.updateAcl(acl);
In the example above, we're retrieving the ACL associated with the "Foo" domain object with identifier number 44. We're then adding an ACE so that a principal named "Samantha" can "administer" the object. The code fragment is relatively self-explanatory, except the insertAce method. The first argument to the insertAce method is determining at what position in the Acl the new entry will be inserted. In the example above, we're just putting the new ACE at the end of the existing ACEs. The final argument is a boolean indicating whether the ACE is granting or denying. Most of the time it will be granting (true), but if it is denying (false), the permissions are effectively being blocked.
Spring Security does not provide any special integration to automatically create, update or delete ACLs as part of your DAO or repository operations. Instead, you will need to write code like shown above for your individual domain objects. It's worth considering using AOP on your services layer to automatically integrate the ACL information with your services layer operations. We've found this quite an effective approach in the past.
Once you've used the above techniques to store some ACL information in the database,
the next step is to actually use the ACL information as part of authorization decision
logic. You have a number of choices here. You could write your own
AccessDecisionVoter
or AfterInvocationProvider
that respectively fires before or after a method invocation. Such classes would use
AclService
to retrieve the relevant ACL and then call
Acl.isGranted(Permission[] permission, Sid[] sids, boolean
administrativeMode)
to decide whether permission is granted or denied.
Alternately, you could use our AclEntryVoter
,
AclEntryAfterInvocationProvider
or
AclEntryAfterInvocationCollectionFilteringProvider
classes. All
of these classes provide a declarative-based approach to evaluating ACL information at
runtime, freeing you from needing to write any code. Please refer to the sample
applications to learn how to use these classes.