At line 10 changed 4 lines. |
* [1] (Optional) Add acegi .jar to your Eclipse classpath |
* [2] Add public Methods |
* [3] Prepare your Actions |
* [3] Configure the MethodSecurityInterceptor |
* [1] (Optional) Add acegi {{.jar}} to your Eclipse classpath |
* [2] Prepare your Actions |
* [3] Update web tests |
* [4] Modify Spring Configuration |
* [5] Modify {{build.xml}} |
At line 25 changed 5 lines. |
!!Add public Methods [#2] |
In the case of the UserManager, we will want to add security on {{saveUser()}} |
%%note __:TODO:__ Fix this... role based security on {{saveUser}} does nothing. remove the unnecessary complexity.%% |
|
!!Prepare your Actions [#3] |
!!Prepare your Actions [#2] |
At line 119 changed 1 line. |
The second consideration for Actions is that public actions (any action that does not require the user to be logged on) can only access public methods on our manager beans. When AppFuse comes out of the box the only action that needs to be modified is {{SignupAction}}. We will need to remove the code that ''automagically'' used to log in a user after signup. It would be possible to still do this, but it is fairly complicated and it's not really that important to me to make the user not have to log in right after creating his account. But the problem with leaving that code in is that is would cause one of the decorator pages to try and access UserManager.getUser() which is protected and an AccessDeniedException will be thrown since our user is not yet logged in. So remove this section of code from {{SignupAction}}: |
The second consideration for Actions is that public actions (any action that does not require the user to be logged on) can only access public methods on our manager beans and the resulting {{success}} page can only access public methods. When AppFuse comes out of the box the only action that needs to be modified is {{SignupAction}}. We will need to remove the code that ''automagically'' used to log in a user after signup. It would be possible to still do this, but it is fairly complicated and it's not really that important to me to make the user not have to log in right after creating his account. But the problem with leaving that code in is that is would cause one of the decorator pages to try and access UserManager.getUser() which is protected. This will cause an AccessDeniedException to be thrown since our user is not yet logged in. So remove this section of code from {{SignupAction}}: |
At line 126 changed 1 line. |
!!Configure the MethodSecurityInterceptor [#3] |
!!Update web tests [#3] |
Because we are no longer able to go directly from our {{SignupAction}} to {{/mainMenu.html}} we will need to modify the Canoo web test to expect to see the login page instead. In {{test/web/web-tests.xml}} update the {{Signup}} target: |
{{{ <verifytitle description="view main menu" text=".*${mainMenu.title}.*" regex="true"/>}}} |
to: |
{{{ <verifytitle description="view login page" text=".*${login.title}.*" regex="true"/>}}} |
|
|
!!Modify Spring Configuration [#4] |
Here is the real meat of what we are tring to do. At this stage we will just use role based authorization, but we will explore more options after geting this to work. We will need to modify two spring files. First we will define the security interceptor in {{web/applicationContext-security.xml}} by adding the following bean definition. |
{{{ |
<bean id="userManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"> |
<property name="authenticationManager"><ref bean="authenticationManager"/></property> |
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property> |
<property name="objectDefinitionSource"> |
<value> |
org.appfuse.service.UserManager.getUser=admin,tomcat |
org.appfuse.service.UserManager.getUsers=admin |
org.appfuse.service.UserManager.removeUser=admin |
</value> |
</property> |
</bean>}}} |
Let's take a minute to look at what this is doing. We are reusing the {{authenticationManager}} and the {{accessDecisionManager}} from the {{filterInvocationInterceptor}} that controls access to specific URI's. So now we are stating which roles are needed to access specific methods of the {{UserManager}}. Because we have not defined any wildcards any method not listed is considered public and does not require the user to be logged in to access. |
|
Next we need to configure the {{userManager}} to utilize the {{userManagerSecurity}} bean we just defined. Edit the {{userManager}} bean in {{src/service/**/service/applicationContext-service.xml}} to look like this: |
{{{ <bean id="userManager" parent="txProxyTemplate"> |
<property name="target"> |
<bean class="org.appfuse.service.impl.UserManagerImpl"> |
<property name="userDAO"><ref bean="userDAO"/></property> |
</bean> |
</property> |
<!-- Override default transaction attributes b/c of LoginCookie methods --> |
<property name="transactionAttributes"> |
<props> |
<prop key="save*">PROPAGATION_REQUIRED</prop> |
<prop key="remove*">PROPAGATION_REQUIRED</prop> |
<prop key="*LoginCookie">PROPAGATION_REQUIRED</prop> |
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop> |
</props> |
</property> |
<!-- REMOVE DURING TEST: Start --> |
<property name="preInterceptors"> |
<list> |
<ref bean="userManagerSecurity"/> |
</list> |
</property> |
<!-- REMOVE DURING TEST: End --> |
</bean>}}} |
You can see that I added those comment tags so we can remove the method security during the unit tests. |
|
!!Modify {{build.xml}} [#5] |
Now we need to modify {{build.xml}} so the Method Security interceptor will be removed during the unit tests. |