Fronting Tomcat with Apache for Spring MVC ERR_TOO_MANY_REDIRECTS error

Viewed 1980

I have a Spring MVC (v4.3.1) Web application running on a Tomcat server(v8.5) which is fronted by an Apache(v2.4) application server being used as a reverse proxy.

I have SSL certificate installed on Apache so that it handles all secure(:443) and non-secure (:80) incoming requests and redirects them to the Tomcat instance.

I want to handle all communication as secured (SSL) with the outside world. But inside between Apache and Tomcat, it is not necessary to communicate through the secure port. That is why Apache redirects all HTTP requests to HTTPS

I also use Spring Security (v4) to handle all user authorization/authentication work, so I have even Register/Login/Logout, etc.

My current server architecture is shown below,

enter image description here

After giving the summary, the problem is,
Whenever I try to access my login page, I am getting ERR_TOO_MANY_REDIRECTS error from Chrome.

Moreover, when I access Tomcat Manager (http://myapp.net:8080/manager/html) and click on my application URL (/MyApp-1.0.0) then ** I can successfully view** my login page without https. (After clicking the application link deployed on tomcat, it opens page: http://myapp.net:8080/MyApp-1.0.0/login) I believe it shows that there is no problem when my web application is running on tomcat instance. They are good together. It suspects me that my problem starts from Apache with SSL.

Apache configuration for virtual hosts:

Listen 80
Listen 443

<VirtualHost *:80>

   ServerAdmin emrecaglar@gmail.com
   ServerName myapp.net
   ServerAlias www.myapp.net
   Redirect  / https://www.myapp.net/

</VirtualHost>
<VirtualHost *:443>

        ServerName  myapp.net
        ServerAlias www.myapp.net
        ProxyPreserveHost On
        ProxyPass /  http://127.0.0.1:8080/MyApp-1.0.0/
        ProxyPassReverse /  http://127.0.0.1:8080/MyApp-1.0.0/

        SSLEngine on
        SSLCertificateFile /root/WWW.myapp.NET.crt
        SSLCertificateKeyFile /root/www.myapp.net.key
        SSLCertificateChainFile /root/dv_chain.txt

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

I dont want to use rewrite rules unless it is critical. I want to handle with Redirect.

Tomcat server.xml configuration :

<Connector   port="8080" protocol="HTTP/1.1"  connectionTimeout="20000" />

There is no connector defined for :8443 as I dont want Tomcat to run on a secure port. Tomcat will communicate only with Apache server.

Spring Security configuration:

@Override
protected void configure(HttpSecurity http) throws Exception {
       http
           .authorizeRequests()
           .antMatchers("/static/**").permitAll()
           .antMatchers("/register*").permitAll()
           .anyRequest().authenticated()
        .and()
           .formLogin()
                  .loginPage("/login")
                  .failureUrl("/login?error=true")
                  .defaultSuccessUrl("/view/home")
                  .permitAll()
        .and()
            .logout().logoutUrl("/logout").logoutSuccessUrl("/login? 
             logout").invalidateHttpSession(true).deleteCookies("auth_code", 
              "JSESSIONID").permitAll();
    }

}  

I have also read some posts about permitAll(), and anonymous() is different, so permitAll() might even trigger a redirect loop so for login page it should be anonymous() however I couldn't validate it. I believe it also needs additional role from spring security perspective.

My Spring Controllers:

 @RequestMapping(value = "/", method = RequestMethod.GET)
    public String homePage(Principal principal) {

        /**
         * Initialize session user if not initialized
         */

          return "redirect:/view/home";
    }

another:

@Controller
@RequestMapping(value = "/view")
public class ViewController
{
 @RequestMapping(value = "/home")
    public String getHomePage(Model model, Principal principal)
    {

        //some logic

        return "home";
    }
}

Web MVC config for login:

@Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");

    }

I have related view resolvers and views (home.jsp, login.jsp)

Chrome Developer console debug outputs for redirects

 General
    Request URL: http://www.myapp.net/MyApp-1.0.0/login
    Request Method: GET
    Status Code: 302 Found
    Remote Address: 207.154.208.158:80
    Referrer Policy: no-referrer-when-downgrade
 Response Header
    HTTP/1.1 302 Found
    Date: Sat, 17 Nov 2018 08:40:04 GMT
    Server: Apache/2.4.18 (Ubuntu)
    Location: https://www.myapp.net/MyApp-1.0.0/login
    Content-Length: 314
    Keep-Alive: timeout=5, max=92
    Connection: Keep-Alive

 Request Header
    Content-Type: text/html; charset=iso-8859-1
    GET /MyApp-1.0.0/login HTTP/1.1
    Host: www.myapp.net
    Connection: keep-alive
    Pragma: no-cache
    Cache-Control: no-cache
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding: gzip, deflate
    Accept-Language: en-US,en;q=0.9
    Cookie: JSESSIONID=8A4E001A841DBC4D55509605FF3E7E23




General
    Request URL: https://www.myapp.net/MyApp-1.0.0/login
    Request Method: GET
    Status Code: 302 
    Remote Address: 207.154.208.158:443
    Referrer Policy: no-referrer-when-downgrade
Response Header
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Connection: Keep-Alive
    Content-Length: 0
    Date: Sat, 17 Nov 2018 08:40:04 GMT
    Expires: 0
    Keep-Alive: timeout=5, max=92
    Location: http://www.myapp.net/MyApp-1.0.0/login
    Pragma: no-cache
    Server: Apache/2.4.18 (Ubuntu)
    X-Content-Type-Options: nosniff
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
 Request Header
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding: gzip, deflate, br
    Accept-Language: en-US,en;q=0.9
    Cache-Control: no-cache
    Connection: keep-alive
    Cookie: JSESSIONID=8A4E001A841DBC4D55509605FF3E7E23
    Host: www.myapp.net
    Pragma: no-cache
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36

Requests loop between these two requests from HTTPS to HTTP and HTPPS again

Apache access.log

67.171.8.29 - - [17/Nov/2018:08:41:59 +0000] "GET /MyApp-1.0.0/login HTTP/1.1" 302 429 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"

Apache error.log

[Sat Nov 17 08:37:59.376633 2018] [mpm_event:notice] [pid 20673:tid 140534533293952] AH00489: Apache/2.4.18 (Ubuntu) mod_jk/1.2.41 OpenSSL/1.0.2g configured -- resuming normal operations
[Sat Nov 17 08:37:59.376707 2018] [core:notice] [pid 20673:tid 140534533293952] AH00094: Command line: '/usr/sbin/apache2'

As you can see, i dont have any SSL related code / config for my spring mvs application and tomcat. They dont need to be aware of that as i want apache be only responsible for SSL and handling https requests and directing to Tomcat.

What i am missing here so that i am causing a redirection loop?

Thanks

0 Answers
Related