user3078383 user3078383 - 9 days ago 6
Java Question

tomcat ssl redirect loop

My application use ssl in tomcat, and run fine when I use port 8080, when I access http://localhost:8080, it redirect to https://localhost:8443.

But when I use a non 8080 port (8081,8082, etc) and I access http://localhost:8081 (or http://localhost:8082, etc), it does a infinite redirect loop to http://localhost:8081 (or http://localhost:8082, etc)

here my server.xml with 8080

<?xml version='1.0' encoding='utf-8'?>

<Server port="8005" shutdown="SHUTDOWN">

<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
<Listener className="org.apache.catalina.core.JasperListener" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>


<Service name="Catalina">

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


<Connector SSLEnabled="true" clientAuth="false" keyAlias="key" keystoreFile="webapps/ROOT/META-INF/my.keystore" keystorePass="pass" maxThreads="150" port="8443" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS"/>


<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />


<Engine name="Catalina" defaultHost="localhost">

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>

<!-- Define the default virtual host
Note: XML Schema validation will not work with Xerces 2.2.
-->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">


</Host>
</Engine>
</Service>
</Server>


and here my server.xml with 8081

<?xml version='1.0' encoding='utf-8'?>

<Server port="8005" shutdown="SHUTDOWN">

<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
<Listener className="org.apache.catalina.core.JasperListener" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>


<Service name="Catalina">

<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />


<Connector SSLEnabled="true" clientAuth="false" keyAlias="key" keystoreFile="webapps/ROOT/META-INF/my.keystore" keystorePass="pass" maxThreads="150" port="8443" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS"/>


<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />


<Engine name="Catalina" defaultHost="localhost">

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>

<!-- Define the default virtual host
Note: XML Schema validation will not work with Xerces 2.2.
-->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">


</Host>
</Engine>
</Service>
</Server>


Can anyone help me?

I'm using tomcat 6

Answer

Another thing to try is to forcibly enable HTTPS for all the apps, in the default web.xml (it should be in tomcat/conf folder next to server.xml), by adding the following to it:

<security-constraint>
        <web-resource-collection>
        <web-resource-name>Protected Context</web-resource-name>
                <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
                    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
</security-constraint>

Note: The below applies to the Tomcat instances with ARP enabled (i.e. most Linux-based installations), but as OP is running a windows-based Tomcat, with the ARP connector already disabled (or not available), it does not apply to him.


Not sure on why do you get a redirect loop, but an apparent problem with your configuration is that you have the APR (native) SSL connector enabled, which does not really work with "keystoreFile", so you should be getting error messages like that in your logs:

java.lang.Exception: Connector attribute SSLCertificateFile must be defined when using SSL with APR 

and SSL should not function for you at all, regardless of a port number used.

And easiest way to defeat it, is to comment out the APR listener:

<!-- <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> -->

to make Tomcat use JSSE connector implementation instead.