0
votes

I am using apache http,mod-jk and two tomcat servers for load balancing of my application which uses spring security. When application is launched, I get below error

 Error code: ERR_TOO_MANY_REDIRECTS 

Has anyone seen this issue before?Is there any configuration to get load balancer work. If I remove spring security from my application, load balancer works fine.

Web.xml

 <?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!-- The definition of the Root Spring Container shared by all Servlets 
    and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-security.xml,/WEB-INF/spring/root-context.xml</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
    <servlet-name>oAuth</servlet-name>
    <servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>
<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>oAuth</servlet-name>
    <url-pattern>/oAuth</url-pattern>
</servlet-mapping>
<session-config>
    <session-timeout>60</session-timeout>
</session-config>
<servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
    <welcome-file>/index.html</welcome-file>
</welcome-file-list>

Spring-Security.xml

  <?xml version="1.0" encoding="UTF-8"?>
   <beans:beans xmlns="http://www.springframework.org/schema/security"
   xmlns:beans="http://www.springframework.org/schema/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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!--HTTP Interceptors for authentication -->
<http pattern="/templates/**" security="none"></http>
<http pattern="/css/**" security="none"></http>
<http pattern="/js/**" security="none"></http>
<http pattern="/lib/**" security="none"></http>
<http pattern="/lib/css/**" security="none"></http>
<http pattern="/lib/js/**" security="none"></http>
<http pattern="/lib/fonts/**" security="none"></http>
<http pattern="/img/**" security="none"></http>
<http pattern="/rest/**" security="none"></http>
<http pattern="/oAuth" security="none"></http>
<http entry-point-ref="entryPoint"
    auto-config="true" use-expressions="true">
    <anonymous enabled="false"></anonymous>
    <custom-filter ref="oAuthFilter" after="SECURITY_CONTEXT_FILTER"></custom-filter>
    <intercept-url pattern="/**" access="hasRole('ROLE_USER')"></intercept-url>
</http>

<authentication-manager alias="upmAuthenticationManager"></authentication-manager>
<beans:bean id="entryPoint" class="auth.EntryPoint">
    <beans:constructor-arg value="/index.html"></beans:constructor-arg>
</beans:bean>

<beans:bean id="oAuthEnd" name="auth.oAuthEnd"
    class="oAuth.OAuthServlet">
    <beans:property name="oAuthFilter" ref="oAuthFilter"></beans:property>
</beans:bean>
<beans:bean id="oAuthFilter" class="auth.filter">
    <beans:property name="id"
        value=""></beans:property>
    <beans:property name="secret"
        value=""></beans:property>
    <beans:property name="url"
        value=""></beans:property>
</beans:bean>

mod-jk configuration

worker.server1.port=8009
worker.server1.host=localhost
worker.server1.type=ajp13

worker.server2.port=9009
worker.server2.host=localhost
worker.server2.type=ajp13

worker.server1.lbfactor=1
worker.server2.lbfactor=1

worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=server1,server2
worker.status.type=status

<VirtualHost *:80>
    JkMount /status status
    JkMount /* loadbalancer
    ServerAdmin webmaster@localhost
    DocumentRoot /data/www/
    <location />
            Require all granted
    </location>

    ErrorLog ${APACHE_LOG_DIR}/www_error.log
    CustomLog ${APACHE_LOG_DIR}/www_access.log combined
 </VirtualHost>
1

1 Answers

1
votes

Apache httpd and mod_jk don't make the trouble I'm afraid.

Hard to say without seeing your config, but I bet that your Spring security config has configured a login page that is secured, so it's allways redirecting to a page you cannot reach.

Could you post your web.xml and security config? And maybe the mod_jk mappings to Tomcat would be helpfull too.

EDIT: I think that setting sticky_session to true could solve the problem. Try adding this to your mod_jk config:

worker.loadbalancer.sticky_session=1

EDIT2: Setting jvmRoute property to values configured in worker.loadbalancer.members solved the problem.

What was happening is that mod_jk uses the value which comes as a suffix in the session cookie to check it against the loadbalancer member names to find out on which has the client the session opened. As the jvmRoute had no value, the JSESSIONID had no suffix so the mod_jk did not know which worker to send the request, so the balancer chooses one worker according to the lbfactor.

As this value is configured with same value to both workers, each incoming request was redirected to the worker that was not chosen in the previous request, so there was no chance to reach the login form neither perform the login (or whatever login mechanism is being used).