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.