Playing Another User Role Using ACEGI
Recently, on one of our projects we had a requirement to allow the ROLE_ADMIN to login as another user without knowing or changing the password of that user. For example 'Jack' has the ROLE_ADMIN and 'Suzy' has the ROLE_USER. Now 'Jack' wants to login as 'Suzy' without knowing her password and carry out some tasks on her behalf acting as her when 'Suzy' is unavailable and some work needs to be done, of course you should provide a mechanism to audit and log whenever 'Jack' wants to play a different role.
This is fairly easy to implement using Acegi
The SwitchUserProcessingFilter in Acegi helps to achieve this functionality. The steps below will show how to configure and use it
1. In the filter chain for acegi, include the filter SwitchUserProcessingFilter as
<!-- ======================== FILTER CHAIN ======================= --> <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /images/**=#NONE# /scripts/**=#NONE# /styles/**=#NONE# / **=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter, anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor,switchUserProcessingFilter </value> </property> </bean>
Make sure that this filter is placed AFTER filterInvocationInterceptor and FilterSecurityInterceptor else any role would be able to do "Role play" rather than ROLE_ADMIN role. Remember it is filter chaining.
2. Define the bean definition for SwitchUserProcessingFilter as
<bean id="switchUserProcessingFilter" class="org.acegisecurity.ui.switchuser.SwitchUserProcessingFilter"> <property name="userDetailsService" ref="userDao" /> <property name="switchUserUrl"><value>/j_acegi_switch_user</value></property> <property name="exitUserUrl"><value>/j_acegi_exit_user</value></property> <property name="targetUrl"><value>/mainMenu.html</value></property> </bean>
here you would just need to change the targetUrl depending on where you need to go after the SWITCH.
userDao is the Dao which you use for your daoAuthenticationProvider
<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="userDao"/> <property name="userCache" ref="userCache"/> <property name="passwordEncoder" ref="passwordEncoder"/> </bean>
3. In your filterInvokationFilter be sure to restrict the access just for ROLE_ADMIN, you definitely don't want all your users logging in as someone else.
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> <property name="authenticationManager" ref="authenticationManager"/> <property name="accessDecisionManager" ref="accessDecisionManager"/> <property name="objectDefinitionSource"> <value> PATTERN_TYPE_APACHE_ANT ...... ...... /j_acegi_switch_user*=ROLE_ADMIN </value> </property> </bean>
4. Now whenever the ROLE_ADMIN wants to role play as another user
The ROLE_ADMIN logs in with his username and password. Then,there should be a link which has the following
where 'vikas' is the username of the user that the ROLE_ADMIN wants to play as. Since only the ROLE_ADMIN should be allowed to see this link you can use the Acegi taglibs to make the link available only to ROLE_ADMIN
<authz:authorize ifAllGranted="ROLE_ADMIN"> <<Switch User Link Here>> </authz:authorize>
When successful switch happens, the user's SecurityContextHolder will be updated to reflect the specified user and will also contain an additional SwitchUserGrantedAuthority which contains the original user. To 'exit' from a user context, the user will then need to access a URL (see exitUserUrl) that will switch back to the original user as identified by the SWITCH_USER_GRANTED_AUTHORITY
To exit from the Role play there should be a link to say
This would bring the ROLE_ADMIN to his own account.
Nested switching and exit is also possible. What this means is that if Jack and Suzy both have ROLE_ADMIN, then Jack can switch to become Suzy who can further switch to become John. Now once the user exits from John realm he comes to Suzy and then on another exit back to Jack.
Conclusion: Switching users is can be easily configured using Acegi. However remember that with 'Great Power comes Great Responsibility' so use this with care.