2 Replies Latest reply on Jul 19, 2015 6:15 AM by David Atkins

    infinite redirect loop using apache proxy to weblogic and scheme="https"

    bmhardy Newbie

      Can anyone offer insight?

       

      I'm new to SEAM.

      We are using the SEAM redirect capability based on setting scheme in pages.xml to switch between http and https depending on the page requested.

       

      When I run our web application using just weblogic and no apache proxy things work fine. In this case I have the default weblogic ports set with http-port=7001 and https-port=7002 in pages.xml.  Also in pages.xml, I set the application to use a default scheme of http as follows:

       

               <page view-id="*" scheme="http">

       

      We set our forgot  password page to use scheme https as follows:

       

                <page view-id="/xhtml/forgotPassword.xhtml" scheme="https">

                          <rewrite pattern="/forgotPassword"/>

                </page>

       

      When we start using the apache proxy we run into problems with the infinite redirect. Since under apache we use ports 80 and 443 for http and https respectively we remove the settings for http-port and https-port from pages.xml. Using the proxy, when we hit the secure page forgotPassword an infinite redirect loop results. On Firefox it says "The page isn't redirecting properly. Firefox has detected that the server is redirecting the request for this address in a way that will never complete."

       

      When we are using the apache proxy to weblogic without any scheme information in pages.xml, I can successfully hit URLs with either http or https simply by typing in the URL. All requests sent from apache on port 80 and 443 are handled successfull by Weblogic on port 7001. I also tried setting up a secure connection from apache to weblogic on port 7002 for using SSL, but this did not seem to help with the redirect problem at all. When we use our apache proxy in this manner the user never sees the 7001 or 7002 port display in the address of the browser.

       

      Any thoughts on why I'm getting this redirect loop or how to avoid it?

       

      Thank you,

      Brian

        • 1. Re: infinite redirect loop using apache proxy to weblogic and scheme="https"
          bmhardy Newbie

          I figured out how to get this work. If you have a configuration with an Apache proxy and a weblogic application server using SEAM and you would like to make

          use of the the SEAM scheme settings to force pages to use https or http follow these steps.

           

           

          1. Make Apache forward to weblogic - You can read about this elsewhere and get this going separately but here are some notes.

           

          A. Get the weblogic apache module and turn it on in the Apache httpd.conf file with this line.

           

          LoadModule weblogic_module modules/mod_wl_22.so


          B. Make apache forward to requests to weblogic for http. Edit the Apache httpd.conf file and add lines similar to these

           

          RedirectMatch ^/$                                            /portal

          RedirectMatch ^/ourwebsite/pub/main$    /portal

           

          <Location /portal>

             SetHandler weblogic-handler

             WebLogicHost hostmachine.yourdomain.com

             WebLogicPort 7001

          </Location>


          C. Turn on SSL in apache forward requests to weblogic for https. Edit the Apache httpd.conf file and add/modify lines similar to these

           

          LoadModule ssl_module modules/mod_ssl.so


          # Secure (SSL/TLS) connections

          Include conf/httpd-ssl.conf

          #

          # Note: The following must must be present to support

          #       starting without SSL on platforms with no /dev/random equivalent

          #       but a statically compiled-in mod_ssl.

          #

          <IfModule ssl_module>

          SSLRandomSeed startup builtin

          SSLRandomSeed connect builtin

          </IfModule>


           

          After you have Apache successfully forwarding requests to weblogic you can follow these steps to make SEAM scheme settings work with a proxy.

          1. In the Apache httpd.conf file turn the mod headers module on with the following line.

           

          LoadModule headers_module modules/mod_headers.so

           

          2. In the Apache httpd.conf file indicate that the request was forwarded with http by adding the following line.

           

          RequestHeader set X-Forwarded-Proto "http"

           

          3. In the Apache httpd-ssl.conf file indicate that the request was forwarded with https by adding the following line after <VirtualHost _default_:443>

           

          RequestHeader set X-Forwarded-Proto "https"

           

          4. In pages.xml set the port numbers that the proxy expects to use. Even if you are using the standard port numbers of 80 for http and 443 for https set these values since these since Pages.encodeScheme will append numbers from the URL. (Your other option here is to extend Pages and overload the encodeScheme method.)

           

          <pages       xmlns="http://jboss.com/products/seam/pages"

                              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                              xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.1.xsd"

                              no-conversation-view-id="/xhtml/map/overviewMap.xhtml"

                              login-view-id="/xhtml/loginRedirector.xhtml"

                              http-port="80" https-port="443">

           

          5. Indicate the deftault site scheme with the SEAM scheme tag in pages.xml. This belongs in your page element with attribute view-id="*".

           

          <page view-id="*" scheme="http">

           

          6. Indicate which pages you would like to be forced to use a different scheme regardless of how the user arrived at the page.

           

          <page view-id="/xhtml/forgotPassword.xhtml" scheme="https">

           

          7. Create a SEAM Filter used to examine if a request was forwarded by apache and force SSL. This uses a RequestWrapper to convert http to https and httpPort to httpsPort when necessary as modules in SEAM ask for the requestURL. This java file is called forwardedHttpsDecoderFilter.

           

          package com.yourapplication.yourpackage;

           

          import java.io.IOException;

          import javax.servlet.FilterChain;

          import javax.servlet.FilterConfig;

          import javax.servlet.ServletException;

          import javax.servlet.ServletRequest;

          import javax.servlet.ServletResponse;

          import javax.servlet.http.HttpServletRequest;

          import javax.servlet.http.HttpServletRequestWrapper;

           

          import org.jboss.seam.Component;

          import org.jboss.seam.ScopeType;

          import org.jboss.seam.annotations.In;

          import org.jboss.seam.annotations.Install;

          import org.jboss.seam.annotations.Logger;

          import org.jboss.seam.annotations.Name;

          import org.jboss.seam.annotations.Scope;

          import org.jboss.seam.annotations.intercept.BypassInterceptors;

          import org.jboss.seam.annotations.web.Filter;

          import org.jboss.seam.log.Log;

          import org.jboss.seam.navigation.Pages;

          import org.jboss.seam.web.AbstractFilter;

           

          @Name("forwardedHttpsDecoderFilter")

          @Scope(ScopeType.APPLICATION)

          @Install

          @BypassInterceptors

          @Filter

          public class ForwardedHttpsDecoderFilter extends AbstractFilter

          {

                private static Integer httpPort;

                private static Integer httpsPort;

           

                // Indicates whether the request was forwarded from a proxy.

                public static final String HEADER_HTTP_X_FORWARDED_PROTO = "X-Forwarded-Proto";

                private static final int DEFAULT_HTTP_PORT = 80;

                private static final int DEFAULT_HTTPS_PORT = 443;

           

                @Logger

                Log log;

           

                public static class SslRequest extends HttpServletRequestWrapper

                {

                       public SslRequest(HttpServletRequest request)

                       {

                            super(request);

                       }

           

                      public HttpServletRequest getRequest()

                      {

                          return (HttpServletRequest) super.getRequest();

                      }

           

                      public StringBuffer getRequestURL()

                      {

                            StringBuffer requestURL = super.getRequestURL();

                            boolean needHttpsScheme = requestURL.indexOf("http://") == 0;

                            if (needHttpsScheme) requestURL.replace(0, 7, "https://");

                            String httpPortString = String.format(":%d", httpPort);

                            boolean needSslPort = requestURL.indexOf(httpPortString) > -1;

                            if (needSslPort)

                            {

                                String newPortValue = String.format(":%d", httpsPort);

                                requestURL = new StringBuffer(requestURL.toString().replace(httpPortString, newPortValue));

                            }

                            return requestURL;

                      }

                }

           

                public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException

                {

                      if (request instanceof HttpServletRequest)

                      {

                            String forwardedScheme = ((HttpServletRequest) request).getHeader(HEADER_HTTP_X_FORWARDED_PROTO);

                            if (forwardedScheme != null && forwardedScheme.equals("https"))

                                  request = new SslRequest((HttpServletRequest) request);

                      }

                     filterChain.doFilter(request, response);

                }

           

           

                public void init(FilterConfig filterConfig) throws ServletException

                {

                       System.out.println("INITIALIZING FILTER ...");

                       try

                       {

                             // Access the Pages component to see what ports have been set.

                            Pages pages = (Pages) Component.getInstance("org.jboss.seam.navigation.pages");

                            httpPort = pages.getHttpPort() != null ? pages.getHttpPort() : DEFAULT_HTTP_PORT;

                            httpsPort = pages.getHttpsPort() != null ? pages.getHttpsPort() : DEFAULT_HTTPS_PORT;

                       }  catch (Throwable ex) {

                           log.error("Could not get port numbers", ex);

                      }

                }

          }

           

           

          This code allows requests to go through to the seam framework, then get redirected by SEAM based on scheme setting in pages.xml and then the filter causes https to be used when it is expected.

           

          I hope this helps others with this issue.

          Brian

          • 2. Re: infinite redirect loop using apache proxy to weblogic and scheme="https"
            David Atkins Newbie

            I know this post is 3 years old, but just wanted to let you know that your filter really helped me out setting up a legacy seam application that's using haproxy for SSL termination.

             

            In my case the whole application uses SSL. The user-facing URL is on port 8443

             

            My setup:

             

            pages.xml:

            <page view-id="*" scheme="https" />


            components.xml

            <navigation:pages https-port="8443" />

             

            haproxy backend

            backend servers-https

              mode http

              option forwardfor

              server localhost 127.0.0.1:8080 weight 1 maxconn 100

              http-request set-header X-Forwarded-Port %[dst_port]

              http-request add-header X-Forwarded-Proto https if { ssl_fc }

              option ssl-hello-chk