How Do I Create a Private Bean Using ACEGI?
Following the directions in the Spring In Action book, I created a small application (only three Java files and two configuration files) so that I could experiment with method-level access control using ACEGI.
However, I continously saw a mysterious message in my log:
Public object - authentication not attempted
So naturally I started looking around the Internet for information about creating private objects. Sadly, there was none. Being stubborn, I downloaded the ACEGI source code to start poking around.
After an hour or so of adding logging messages and tracing the code, I saw the following message in my logging of the MethodDefinitionMap.lookupAttributes method:
...MethodDefinitionMap; this: {...public java.lang.String
com.affy.BeanA.getValue()=[ROLE_FIELD_OPS, ROLE_DIRECTORY,
ROLE_PRESIDENT]}
...MethodDefinitionMap; method: public abstract java.lang.String
com.affy.IBeanA.getValue()
At first I thought the problem lay in the abstract keyword. But then I realized that my Spring configuration file contained:
<bean id='securityInterceptor' class='...MethodSecurityInterceptor'>
...
<property name='objectDefinitionSource'>
<value>
com.affy.BeanA.setValue=ROLE_PRESIDENT
com.affy.BeanA.getValue=ROLE_FIELD_OPS,ROLE_DIRECTORY,ROLE_PRESIDENT
</value>
</property>
</bean>
The object definition specified the BeanA implementation instead of the Interface. Once I changed to use com.affy.IBean I saw the following message:
...AbstractSecurityInterceptor - Secure object: invocation: method 'setValue', arguments [FOOBAR]; target is of class [com.affy.BeanA]; ConfigAttributes: [ROLE_PRESIDENT]
Now the newly created object was private!
CONCLUSION Use Interfaces in the objectDefinitionSource specification.