Announcement Announcement Module
Collapse
No announcement yet.
RedirectView and ACEGI BUg?? Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • RedirectView and ACEGI BUg??

    I've got a strange problem with redirecting from a Controller implementing class to a SimpleFormController by returning the name in the returned ModelAndView object. The first time... ACEGI filters the request, sees no security, and sends to the login page. After logging in, they are sent to the SecTestController which implements Controller and return a new ModelAndView which corresponds to a RedirectView. This name is then resolved and picked up by the xxx-servlet.xml and sends the request to a SimpleFormController which doesn't really do much. I have dummied down the majority of the code to make it do as little as possible and still demonstrate the problem.

    I just find it really odd that the problem only exhibits itself after the login occurs. Once you log in, if you go back to the main page and go through the scenario, it will just hang instead of the filter figuring out that the user is already logged in and continuing along the chain as expected. If I am doing something wrong here let me know, and if it's a bug (i've looked but haven't found anything regarding it), please let me know.

    Code follows:

    web.xml
    Code:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    
    <!DOCTYPE web-app PUBLIC
    	"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    	"http&#58;//java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
    
    	<display-name>Sec Test</display-name>
    
    	<description>
    		Simple app to test the authentication system.
    	</description>
    
    	<!--
    		- Key of the system property that should specify the root directory of this
    		- web app. Applied by WebAppRootListener or Log4jConfigListener.
    	-->
    	<context-param>
    		<param-name>webAppRootKey</param-name>
    		<param-value>sectest.root</param-value>
    	</context-param>
    
    	<!--
    		- Location of the Log4J config file, for initialization and refresh checks.
    		- Applied by Log4jConfigListener.
    	-->
    
    
    	<!--
    		- Location of the XML file that defines the root application context.
    		- Applied by ContextLoaderServlet.		
    	-->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>/WEB-INF/applicationContext.xml</param-value>
    	</context-param>
    
    	<!-- Acegi Filters -->
    
    	<filter>
    		<filter-name>Acegi Channel Processing Filter</filter-name>
    		<filter-class>
    			net.sf.acegisecurity.util.FilterToBeanProxy
    		</filter-class>
    		<init-param>
    			<param-name>targetClass</param-name>
    			<param-value>
    				net.sf.acegisecurity.securechannel.ChannelProcessingFilter
    			</param-value>
    		</init-param>
    	</filter>
    
    	<filter>
    		<filter-name>Acegi CAS Processing Filter</filter-name>
    		<filter-class>
    			net.sf.acegisecurity.util.FilterToBeanProxy
    		</filter-class>
    		<init-param>
    			<param-name>targetClass</param-name>
    			<param-value>
    				net.sf.acegisecurity.ui.cas.CasProcessingFilter
    			</param-value>
    		</init-param>
    	</filter>
    
    	<filter>
    		<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
    		<filter-class>
    			net.sf.acegisecurity.util.FilterToBeanProxy
    		</filter-class>
    		<init-param>
    			<param-name>targetClass</param-name>
    			<param-value>
    				net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter
    			</param-value>
    		</init-param>
    	</filter>
    
    	<!-- Obtains Authentication from HttpSession attribute, puts it into
    		ContextHolder for request duration, proceeds with request, then
    		copies Authentication from ContextHolder back into HttpSession -->
    	<filter>
    		<filter-name>
    			Acegi Security System for Spring HttpSession Integration
    			Filter
    		</filter-name>
    		<filter-class>
    			net.sf.acegisecurity.util.FilterToBeanProxy
    		</filter-class>
    		<init-param>
    			<param-name>targetClass</param-name>
    			<param-value>
    				net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter
    			</param-value>
    		</init-param>
    	</filter>
    
    	<filter>
    		<filter-name>Acegi HTTP Request Security Filter</filter-name>
    		<filter-class>
    			net.sf.acegisecurity.util.FilterToBeanProxy
    		</filter-class>
    		<init-param>
    			<param-name>targetClass</param-name>
    			<param-value>
    				net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter
    			</param-value>
    		</init-param>
    	</filter>
    
    	<filter-mapping>
    		<filter-name>Acegi Channel Processing Filter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    
    	<filter-mapping>
    		<filter-name>Acegi CAS Processing Filter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    
    	<filter-mapping>
    		<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    
    	<filter-mapping>
    		<filter-name>
    			Acegi Security System for Spring HttpSession Integration
    			Filter
    		</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    
    	<filter-mapping>
    		<filter-name>Acegi HTTP Request Security Filter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    
    
    
    	<!-- Uncomment for JBoss -->
    
    
    	<listener>
    		<listener-class>
    			org.springframework.web.context.ContextLoaderListener
    		</listener-class>
    	</listener>
    
    	<!--
    		- Loads the root application context of this web app at startup,
    		- by default from "/WEB-INF/applicationContext.xml".
    		- Note that it is preferable to use ContextLoaderListener in a servlet container
    		- that follows the Servlet 2.4 initialization order &#40;most Servlet 2.3 containers do&#41;.
    		-
    		- Use WebApplicationContextUtils.getWebApplicationContext&#40;servletContext&#41;
    		- to access it anywhere in the web application, outside of the framework.
    		-
    		- The root context is the parent of all servlet-specific contexts.
    		- This means that its beans are automatically available in these child contexts,
    		- both for getBean&#40;name&#41; calls and &#40;external&#41; bean references.
    	-->
    	<servlet>
    		<servlet-name>context</servlet-name>
    		<servlet-class>
    			org.springframework.web.context.ContextLoaderServlet
    		</servlet-class>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    
    	<!--
    		- Spring web MVC servlet that dispatches requests to registered handlers.
    		- Has its own application context, by default defined in "&#123;servlet-name&#125;-servlet.xml",
    		- i.e. "locknload-servlet.xml" in this case.
    	-->
    	<servlet>
    		<servlet-name>sectest</servlet-name>
    		<servlet-class>
    			org.springframework.web.servlet.DispatcherServlet
    		</servlet-class>
    		<load-on-startup>2</load-on-startup>
    	</servlet>
    
    	<!--
    		- Dispatcher servlet mapping for the main web user interface.
    	-->
    	<servlet-mapping>
    		<servlet-name>sectest</servlet-name>
    		<url-pattern>*.htm</url-pattern>
    	</servlet-mapping>
    
    	<welcome-file-list>
    		<welcome-file>index.jsp</welcome-file>
    	</welcome-file-list>
    
    </web-app>
    applicationContext.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
    
    <!--
      - Application context definition for LockNLoad's business layer.
    	- Contains bean references to the transaction manager and to the DAOs in
    	- dataAccessContext-local.xml &#40;see web.xml's "contextConfigLocation"&#41;.
    	-->
    <beans>
       
        <!-- ========================= GENERAL DEFINITIONS ========================= -->
    
    	
    	
    	<!-- ========================= BUSINESS OBJECT DEFINITIONS ======================== -->
    
    	<!-- AOP advice used to send confirmation email after ticket has been submitted -->
    	
    	<!-- a parent bean definition which is a 'template' or base definition for
    	     transaction proxies. It is set as lazy-init, since it is never
    		 supposed to be instantiated itself. -->
    	<bean id="baseTxProxy" lazy-init="true"
    	      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager"><ref bean="myTransactionManager"/></property>
    		<property name="transactionAttributes">
    			<props>
    				<prop key="*">PROPAGATION_REQUIRED</prop>
    			</props>
    		</property>
    	</bean>
    	
    	<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
    	
    	<!-- RunAsManager -->
    	<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
         	<property name="key"><value>my_run_as_password</value></property>
     	</bean>
    
    	<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
    	
     	<bean id="runAsAuthenticationProvider" class="net.sf.acegisecurity.runas.RunAsImplAuthenticationProvider">
         	<property name="key"><value>my_run_as_password</value></property>
     	</bean>
    
    	<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
    		<property name="providers">
    		  <list>
    		    <ref local="runAsAuthenticationProvider"/>
    		    <ref local="casAuthenticationProvider"/>
    		  </list>
    		</property>
    	</bean>
    
    	<bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
      		<property name="userMap">
    			<value>
    				jwinans=PASSWORD_NOT_USED,ROLE_SUPPORT
    				tbrown=PASSWORD_NOT_USED,ROLE_MANAGER
    				jonw=PASSWORD_NOT_USED,ROLE_CSR
    			</value>
    		</property>
    	</bean>
    	
    	<bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter">
    		<property name="authenticationManager"><ref local="authenticationManager"/></property>
    		<property name="authenticationEntryPoint"><ref local="basicProcessingFilterEntryPoint"/></property>
    	</bean>
    
    	<bean id="basicProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
    		<property name="realmName"><value>SecTest Realm</value></property>
    	</bean>
    
    	<bean id="httpSessionIntegrationFilter" class="net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter"/>
    
    	<bean id="casAuthenticationProvider" class="net.sf.acegisecurity.providers.cas.CasAuthenticationProvider">
    		<property name="casAuthoritiesPopulator"><ref local="casAuthoritiesPopulator"/></property>
    		<property name="casProxyDecider"><ref local="casProxyDecider"/></property>
    		<property name="ticketValidator"><ref local="casProxyTicketValidator"/></property>
    		<property name="statelessTicketCache"><ref local="statelessTicketCache"/></property>
    		<property name="key"><value>my_password_for_this_auth_provider_only</value></property>
    	</bean>
    
    	<bean id="casProxyTicketValidator" class="net.sf.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator">
    		<property name="casValidate"><value>https&#58;//localhost&#58;8443/cas/proxyValidate</value></property>
    		<!-- <property name="proxyCallbackUrl"><value>https&#58;//localhost&#58;8443/locknload/casProxy/receptor</value></property> -->
    		<property name="serviceProperties"><ref local="serviceProperties"/></property>
            <property name="trustStore"><value>C&#58;/java/lib/security/cacerts</value></property>
    	</bean>
    
    	<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
        
       <bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
          <property name="cacheManager">
             <ref local="cacheManager"/>
          </property>
          <property name="cacheName">
             <value>statelessTicketCache</value>
          </property>
       </bean>
    	<bean id="statelessTicketCache" class="net.sf.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache">
    		<property name="cache"><ref local="userCacheBackend"/></property>
    	</bean>
    
    	<bean id="casAuthoritiesPopulator" class="net.sf.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator">
    		<property name="authenticationDao"><ref local="inMemoryDaoImpl"/></property>
    	</bean>
    
    	<bean id="casProxyDecider" class="net.sf.acegisecurity.providers.cas.proxy.RejectProxyTickets">
    	</bean>
    
    	<bean id="serviceProperties" class="net.sf.acegisecurity.ui.cas.ServiceProperties">
    		<property name="service"><value>https&#58;//localhost&#58;8443/sectest/j_acegi_cas_security_check</value></property>
    		<property name="sendRenew"><value>false</value></property>
    	</bean>
    	
    	<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
    
    	<!-- An access decision voter that reads ROLE_* configuaration settings -->
    	<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
    	
    	
    	<!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== -->
    	
    	<bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter">
    		<property name="channelDecisionManager"><ref local="channelDecisionManager"/></property>
     		<property name="filterInvocationDefinitionSource">
    			<value>
    			    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    				\A/secure/.*\Z=REQUIRES_SECURE_CHANNEL
    				\A/j_acegi_cas_security_check.*\Z=REQUIRES_SECURE_CHANNEL	
    				\A.*\Z=REQUIRES_INSECURE_CHANNEL
    			</value>
    		</property>
    	</bean>
    
    	<bean id="channelDecisionManager" class="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl">
    	    <property name="channelProcessors">
          		<list>
     	        	<ref local="secureChannelProcessor"/>
            		<ref local="insecureChannelProcessor"/>
         		</list>
    	    </property>
    	</bean>
    
    	<bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/>
    	<bean id="insecureChannelProcessor" class="net.sf.acegisecurity.securechannel.InsecureChannelProcessor"/>
    
    	<!-- ===================== HTTP REQUEST SECURITY ==================== -->
    
    	<bean id="casProcessingFilter" class="net.sf.acegisecurity.ui.cas.CasProcessingFilter">
    		<property name="authenticationManager"><ref local="authenticationManager"/></property>
    		<property name="authenticationFailureUrl"><value>/casfailed.jsp</value></property>
    		<property name="defaultTargetUrl"><value>/</value></property>
    		<property name="filterProcessesUrl"><value>/j_acegi_cas_security_check</value></property>
    	</bean>
    
    	<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
    		<property name="filterSecurityInterceptor"><ref local="filterInvocationInterceptor"/></property>
    		<property name="authenticationEntryPoint"><ref local="casProcessingFilterEntryPoint"/></property>
    	</bean>
    
    	<bean id="casProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.cas.CasProcessingFilterEntryPoint">
    		<property name="loginUrl"><value>https&#58;//localhost&#58;8443/cas/login</value></property>
    		<property name="serviceProperties"><ref local="serviceProperties"/></property>
    	</bean>
    
    	<bean id="httpRequestAccessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
       		<property name="allowIfAllAbstainDecisions"><value>false</value></property>
    		<property name="decisionVoters">
    		  <list>
    		    <ref local="roleVoter"/>
    		  </list>
    		</property>
    	</bean>
    
    	<!-- Note the order that entries are placed against the objectDefinitionSource is critical.
    	     The FilterSecurityInterceptor will work from the top of the list down to the FIRST pattern that matches the request URL.
    	     Accordingly, you should place MOST SPECIFIC &#40;ie a/b/c/d.*&#41; expressions first, with LEAST SPECIFIC &#40;ie a/.*&#41; expressions last -->
    	<bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
        	<property name="authenticationManager"><ref local="authenticationManager"/></property>
        	<property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/></property>
        	<property name="runAsManager"><ref local="runAsManager"/></property>
     		<property name="objectDefinitionSource">
    			<value>
    			    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    				\A/secure/support/.*\Z=ROLE_SUPPORT
    				\A/secure/manage/.*\Z=ROLE_SUPPORT,ROLE_MANAGER
    				\A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_CSR,ROLE_SUPPORT,ROLE_MANAGER
    			</value>
    		</property>
    	</bean>
    	
    	<!-- BASIC Regular Expression Syntax &#40;for beginners&#41;&#58;
    	     
    	     \A means the start of the string &#40;ie the beginning of the URL&#41;
    	     \Z means the end of the string &#40;ie the end of the URL&#41;
    	     .  means any single character
    	     *  means null or any number of repetitions of the last expression &#40;so .* means zero or more characters&#41;
    	     
    	     Some examples&#58;
    	     
    	     Expression&#58;   \A/my/directory/.*\Z
    	     Would match&#58;    /my/directory/
    	                     /my/directory/hello.html
    	     
    	     Expression&#58;   \A/.*\Z
    	     Would match&#58;    /hello.html
    	                     /
    	     
    	     Expression&#58;   \A/.*/secret.html\Z
    	     Would match&#58;    /some/directory/secret.html
    	                     /another/secret.html
    	     Not match&#58;      /anothersecret.html &#40;missing required /&#41;
    	-->
    	
    	
    </beans>
    sectest-servlet.xml
    Code:
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
    
    
    <beans>
    	
    	<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
    		<property name="basename"><value>views</value></property>
    	</bean>
    	
    	
    	<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    		<property name="mappings">
    			<props>
    				<prop key="/secure/secTest.htm">secTestController</prop>
    				<prop key="/secure/test.htm">testFormController</prop>			
    			</props>
    		</property>
    	</bean>
    
     	
     	<!--  Just an extended Controller which makes the decision on where to forward / redirect -->
    	<bean id="secTestController" class="tut.sectest.SecTestController">
    		<property name="testView"><value>testFormRedirect</value></property>
    	</bean>
    	
    	<!--  An extended SimpleFormController which shows a simple message -->
    	<bean id="testFormController" class="tut.sectest.TestFormController">
    		<property name="formView"><value>testForm</value></property>
    		<property name="successView"><value>testFormRedirect</value></property>
    		<property name="msg"><value>Hello, I work now.</value></property>
    		<property name="commandName"><value>message</value></property>
    		<property name="commandClass"><value>java.lang.String</value></property>
    		
    	</bean>
    
    	
    </beans>
    views.properties
    Code:
    testFormRedirect.class=org.springframework.web.servlet.view.RedirectView
    testFormRedirect.url=/sectest/secure/test.htm
    
    testForm.class=org.springframework.web.servlet.view.JstlView
    testForm.url=/WEB-INF/secure/test.jsp
    index.jsp
    Code:
    <% response.sendRedirect&#40;"/sectest/secure/secTest.htm"&#41;;%>
    test.jsp
    Code:
    <%@ include file="includeLibs.jsp" %>
    <html>
    <head>
    <title>Sec Test</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <body>
    This is a test.
    </body>
    </html>
    tut.sectest.SecTestController
    Code:
    package tut.sectest;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import java.util.*;
    
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;
    
    /**
     * @author tbrown
     *
     * TODO To change the template for this generated type comment go to
     * Window - Preferences - Java - Code Style - Code Templates
     */
    public class SecTestController implements Controller &#123;
    
    	private String testView;
    	
    	public void setTestView&#40;String testView&#41; &#123; this.testView = testView; &#125;
    	
    	public ModelAndView handleRequest&#40;HttpServletRequest request, HttpServletResponse response&#41;
    		throws Exception &#123;
    		
    		return new ModelAndView&#40;testView&#41;;		
    		
    	&#125;
    &#125;
    tut.sectest.TestFormController
    Code:
    package tut.sectest;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.validation.BindException;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.SimpleFormController;
    
    
    /**
     * @author tbrown
     *
     * TODO To change the template for this generated type comment go to
     * Window - Preferences - Java - Code Style - Code Templates
     */
    public class TestFormController extends SimpleFormController &#123;
    	
    	private String msg;
    	
    	public void setMsg&#40;String msg&#41; &#123; this.msg = msg; &#125;
    	
    
    	protected ModelAndView onSubmit&#40;HttpServletRequest request, HttpServletResponse response, Object command,
    		BindException errors&#41; throws Exception &#123;
    		
    		return new ModelAndView&#40;getSuccessView&#40;&#41;&#41;;			
    	&#125;
    	
    	protected Object formBackingObject&#40;HttpServletRequest request&#41; throws Exception &#123;
    		
    		return msg;		
    	&#125;
    &#125;
    [/b]

  • #2
    Upgrade ACEGI Lib's Fixed

    I upgraded to the 0.8.0 ACEGI libraries, and remodelled the xml files from the sample contacts application, and it seems to have fixed the problem.

    Comment


    • #3
      Still doesn't work.

      Forgot to include the channelProcessingFilter in the filterProxyChain.

      Still doesn't work.

      I don't see what's so hard about redirecting to a SimpleFormController from another controller.

      Comment


      • #4
        So your redirection basically works now, unless you also include ChannelProcessingFilter in FilterProxyChain? Have you tried using ChannelProcessingFilter directly from web.xml via FilterToBeanProxy (ie no FilterProxyChain)? Also, have you tried watching the DEBUG-level logging to see what the Acegi Security classes are detecting in terms of the URIs to redirect to?

        Comment

        Working...
        X