Raible's Wiki

Raible Designs
Wiki Home
News
Recent Changes

AppFuse

Homepage
  - Korean
  - Chinese
  - Italian
  - Japanese

QuickStart Guide
  - Chinese
  - French
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish
  - Japanese

User Guide
  - Korean
  - Chinese

Tutorials
  - Chinese
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish

FAQ
  - Korean

Latest Downloads

Other Applications

Struts Resume
Security Example
Struts Menu

Set your name in
UserPreferences


Referenced by
AppFuseSecurityMetho...




JSPWiki v2.2.33

[RSS]


Hide Menu

AppFuseSecurityMethods2


Difference between version 5 and version 4:

At line 18 added 2 lines.
Because we want new users to be able to create a new account, and we want existing users (who are not {{admin}}'s) to only be able to update their own User object we need two separate methods in our {{UserManager}} to handle this. One method, {{updateUser()}}, will be secured and the other, {{saveUser()}} will not.
%%note __NOTE:__ These methods should probably be {{updateUser()}} and {{createUser()}}, but I wanted to change as little as possible to get this working. You should be able to figure out how to make this change after understanding this tutorial.%%
At line 19 changed 1 line.
!! Modify txProxyTemplate configuration [#2]
We need to add or modify the following code to these classes:
{{UserManagerTest.testSaveUser()}} change:
[{Java2HtmlPlugin
userManager.saveUser(user);
}]
to:
[{Java2HtmlPlugin
userManager.updateUser(user);
}]
At line 21 changed 1 line.
!! Create the OwnerVoter [#3]
{{UserManager}} add:
[{Java2HtmlPlugin
/**
* Updates a user's information
*
* @param user the user's information
* @throws UserExistsException
*/
public void updateUser(User user) throws UserExistsException;
}]
{{UserManagerImpl}} add:
[{Java2HtmlPlugin
/**
* @see org.appfuse.service.UserManager#saveUser(org.appfuse.model.User)
*/
public void updateUser(User user) throws UserExistsException {
saveUser(user);
}
}]
%%note __NOTE:__ These manager methods should probably be smarter by making {{saveUser()}} only be able to save a new user and {{updateUser()}} only update an existing user, but for now this is what we have.%%
{{UserAction.save()}} change:
[{Java2HtmlPlugin
mgr.saveUser(user);
}]
to:
[{Java2HtmlPlugin
mgr.updateUser(user);
}]
!! Modify {{txProxyTemplate}} configuration [#2]
Because we are now saving a record with a method that does not fit the pattern {{save*}} we need to update the {{txProxyTemplate}} bean in {{applicationContext-service.xml}}.
{{{
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
}}}
!! Create the {{OwnerVoter}} [#3]
At line 24 changed 1 line.
!! Modify userManagerSecurity configuration [#4]
!! Modify {{userManagerSecurity}} configuration [#4]
We need to define a few more beans and modify the bean definition of {{userManagerSecurity}} in {{applicationContext-security.xml}}.
At line 87 added 55 lines.
The {{OwnerVoter}} only works on Method Invocation security, so we now need to have a seperate {{accessDecisionManager}} for {{userManagerSecurity}} bean from the one being used for URI security.
{{{
<bean id="businessAccessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
<property name="decisionVoters">
<list>
<ref local="roleVoter"/>
<ref local="userOwnerVoter"/>
<ref local="usernameStringOwnerVoter"/>
</list>
</property>
</bean>
}}}
You will notice that {{businessAccessDecisionManager}} now has references to a couple of new beans based on {{OwnerVoter}}. The first one looks for methods that have an argument of type {{User}} and grants access when the authenticated user's username matches {{User.getUsername()}} on that object.
{{{
<bean id="userOwnerVoter" class="org.appfuse.security.OwnerVoter">
<property name="processConfigAttribute">
<value>OWNER_USER_EQUALS</value></property>
<property name="processDomainObjectClass">
<value>org.appfuse.model.User</value></property>
<property name="internalMethod">
<value>getUsername</value></property>
</bean>
}}}
The second bean is for methods that are passed a username {{String}} rather than the entire object. In this case the string is compared to the authenticated user's username
{{{
<bean id="usernameStringOwnerVoter" class="org.appfuse.security.OwnerVoter">
<property name="processConfigAttribute">
<value>OWNER_STRING_EQUALS</value></property>
<property name="processDomainObjectClass">
<value>java.lang.String</value></property>
<property name="internalMethod">
<value>toString</value></property>
</bean>
}}}
Next we need to update the {{userManagerSecurity}} defintion to utilize the {{OwnerVoter}}'s we just defined.
{{{
<bean id="userManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
<property name="objectDefinitionSource">
<value>
org.appfuse.service.UserManager.getUser=admin,OWNER_STRING_EQUALS
org.appfuse.service.UserManager.getUsers=admin
org.appfuse.service.UserManager.removeUser=admin,OWNER_STRING_EQUALS
org.appfuse.service.UserManager.updateUser=admin,OWNER_USER_EQUALS
</value>
</property>
</bean>
}}}
You will notice that {{saveUser}} is not in the list because it is a public method, and the {{tomcat}} role is no longer needed because the user must be authenticated in order for either of the {{OwnerVoter}}'s to grant access.
At line 143 added 1 line.
{{test-all}} should now work. It is difficult to show any differences in the security now that we have added this to the service layer. That is because the User object is pretty well protected in the UserAction.

Back to AppFuseSecurityMethods2, or to the Page History.