Skip to content

Acegi 1.0.8 Example (Life Without the SecurityEnforcementFilter)

Note; This was my first day of adding Acegi to an existing webapp.

You can find a lot of Acegi security framework examples on the web these days. Unfortunately, nearly all of the examples use Acegi use the pre 1.0 version, which is before someone removed the SecurityEnforcementFilter..
The official description of this event follows:

org.acegisecurity.intercept.web.SecurityEnforcementFilter has moved to a new location and name, org.acegisecurity.ui.ExceptionTranslationFilter. In addition, the “filterSecurityInterceptor” property on the old SecurityEnforcementFilter class has been removed. This is because SecurityEnforcementFilter will no longer delegate to FilterSecurityInterceptor as it has in the past. Because this delegation feature has been removed (see SEC-144 for a background as to why), please add a new filter definition for FilterSecurityInterceptor to the end of your FilterChainProxy. Generally you’ll also rename the old SecurityEnforcementFilter entry in your FilterChainProxy to ExceptionTranslationFilter, more accurately reflecting its purpose. If you are not using FilterChainProxy (although we recommend that you do), you will need to add an additional filter entry to web.xml and use FilterToBeanProxy to access the FilterSecurityInterceptor.

Which is another way of saying if you need to implement a security system in a hurry like 90% of the developers out there, you’re SOL. This description will probably make a lot of sense to those familiar with Acegi, but it’s a daunting task to figure out if you’re new to the system. My efforts and example with Acegi 1.0.7 follow after the jump.

I joined a small team working on a small internal app and was assigned the task of introducing Acegi to the application.
They are using Spring MVC, Hibernate, and HSQLDB for development. Because Acegi introduces so many new bean wirings, I chose to introduce the security framework as a new XML file, calling it securityContext.xml.

The relevant pieces of the web.xml look like this:

<context-param></context-param>
<param-name>locatorFactorySelector</param-name> 		<!--
This item points to one beanRefContext. The beanRefContext then
holds a reference to the base applicationContext.xml.
-->
<param-value> 			classpath:/resources/org/reverttoconsole/app/beanRefContext.xml 		</param-value>

and

	<filter>
    	<filter-name>Acegi Filter Chain Proxy</filter-name>
		<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
        <init-param>
        	<param-name>targetClass</param-name>
            <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
        </init-param>
    </filter>
    <filter>
		<filter-name>LogoutFilter</filter-name>
		<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
		<init-param>
			<param-name>targetBean</param-name>
			<param-value>logoutFilter</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>LogoutFilter</filter-name>
		<url-pattern>/logout.do</url-pattern>
	</filter-mapping>
    <filter-mapping>
    	<filter-name>Acegi Filter Chain Proxy</filter-name>
		<url-pattern>/*</url-pattern>
    </filter-mapping>

The beanRefContext picks up my security xml addition:

<beans xmlns="http://www.springframework.org/schema/beans">
</beans>	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"&gt;

	<bean id="org.reverttoconsole.app.context">
</bean>		class="org.springframework.context.support.ClassPathXmlApplicationContext"&gt;
		<constructor-arg>
<list>
				<value>resources/org/reverttoconsole/app/applicationContext.xml</value>
				<value>resources/org/reverttoconsole/app/securityContext.xml</value>
			</list>
		</constructor-arg>

and my additional security wiring looks like this:


<!--
  - A simple "base bones" Acegi Security configuration.
  -->

<beans>

	<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
			<value><!--[CDATA[
				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
				/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
			]]--></value>
		</property>
	</bean>

	<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"></bean>

	<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
		<constructor-arg value="/jsp/logout.jsp"/> <!-- URL redirected to after logout -->
		<constructor-arg>
			<list>
				<ref bean="rememberMeServices"/>
				<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
			</list>
		</constructor-arg>
		<property name="filterProcessesUrl" value="/logout.do" />
	</bean>

	<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="authenticationFailureUrl" value="/jsp/login.jsp?login_error=1"></property>
<property name="defaultTargetUrl" value="/index.html"></property>
<property name="filterProcessesUrl" value="/jsp/j_acegi_security_check"></property>
<property name="rememberMeServices" ref="rememberMeServices"></property>
	</bean>

	<bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"></bean>

	<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="rememberMeServices" ref="rememberMeServices"></property>
	</bean>

	<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="changeThis"></property>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"></property>
	</bean>

	<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
			<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/jsp/login.jsp"></property>
<property name="forceHttps" value="false"></property>
			</bean>
		</property>
<property name="accessDeniedHandler">
			<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/jsp/accessDenied.jsp"></property>
			</bean>
		</property>
	</bean>

	<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="accessDecisionManager">
			<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"></property>
<property name="decisionVoters">
<list>
						<bean class="org.acegisecurity.vote.RoleVoter"></bean>
						<bean class="org.acegisecurity.vote.AuthenticatedVoter"></bean>
					</list>
				</property>
			</bean>
		</property>
<!-- Defines two role groups; administrators and consultants -->
<property name="objectDefinitionSource">
			<value><!--[CDATA[
				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
				/admin/**=ROLE_SUPERVISOR
				/consultant/**=IS_AUTHENTICATED_REMEMBERED
				/**=IS_AUTHENTICATED_ANONYMOUSLY
			]]--></value>
		</property>
	</bean>

	<bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="userDetailsService"></property>
<property name="key" value="changeThis"></property>
	</bean>

	<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
				<ref local="daoAuthenticationProvider">
				<bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key" value="changeThis1"></property>
				</bean>
				<bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="changeThis1"></property>
				</bean>
			</ref>
		</list>
	</property>

	<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"></property>
	</bean>

	<!-- UserDetailsService is the most commonly frequently Acegi Security interface implemented by end users -->
	<bean id="userDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
<property name="userProperties">
			<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="/WEB-INF/users.properties"></property>
			</bean>
		</property>
	</bean>

	<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
	<bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"></bean>

</bean></constructor-arg></bean></beans>

Note: this is borrowed almost completely from acegi-security-samples-tutorial. I’d recommend checking it out before using this example and particularly before looking for other examples online (it will save you a lot of time).
I’ve modified the section for roles; my application has two roles- administrators and consultants.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*