Search code examples
tomcatsslhttpsbasic-authentication

Tomcat SSL https port issues


At the moment Im trying to improve my tomcat know how. Im trying to set up tomcat with SSL. The idea is that I got the path with /app which doesnt need any authorisation, and the path /admin, where basis authentication is needed. I guess Its just a lack of general knowhow about SSL, that I cant understand what happens.

When I use the url http://localhost:8080/myapp/app/ it works and it shows my page. Now I change /app to /admin. After that my url is https://localhost/myapp/admin and it doesnt work, because the 8443 port is missing. I dont understand why does it automatically change to https but the port is missing after that? What is my problem and how can I solve it?

Any help is highly appreciated :)

My server.xml:

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

<Listener className="org.apache.catalina.core.JasperListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>

<Service name="Catalina">

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

    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystoreFile="${catalina.home}/myapp.keystore"
               keystorePass="histackoverflow"/>

    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>

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

        <Realm className="org.apache.catalina.realm.MemoryRealm" />

        <Host name="localhost" appBase="webapps"
              unpackWARs="true" autoDeploy="true">

            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                   prefix="localhost_access_log." suffix=".txt"
                   pattern="%h %l %u %t &quot;%r&quot; %s %b"/>

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

My web.xml looks like that:

<servlet>
    <servlet-name>MyApp REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>main.ch.myapp.resource.app</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Myapp REST Service</servlet-name>
    <url-pattern>/app-api/*</url-pattern>
</servlet-mapping>


<servlet>
    <servlet-name>MyApp Admin REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>main.ch.myapp.resource.admin</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>MyApp Admin REST Service</servlet-name>
    <url-pattern>/admin-api/*</url-pattern>
</servlet-mapping>

<security-constraint>
    <web-resource-collection>
        <web-resource-name>MyApp Admin</web-resource-name>
        <url-pattern>/admin/*</url-pattern>
        <url-pattern>/admin-api/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>admin</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>
<login-config>
    <auth-method>BASIC</auth-method>
</login-config>

Solution

  • The change to https is done because of <transport-guarantee>CONFIDENTIAL</transport-guarantee> included in <security-constraint>.

    Take a look at:
    The Java EE 6 Tutorial, Volume I. Specifying Security Constraints
    The Java EE 6 Tutorial, Volume I. Specifying a Secure Connection

    Specifying a Secure Connection

    A user data constraint (TutorialUser-data-constraint in the deployment descriptor) contains the transport-guarantee element. A user data constraint can be used to require that a protected transport layer connection such as HTTPS (HTTP over SSL) be used for all constrained URL patterns and HTTP methods specified in the security constraint. The choices for transport guarantee include CONFIDENTIAL, INTEGRAL, or NONE. If you specify CONFIDENTIAL or INTEGRAL as a security constraint, it generally means that the use of SSL is required, and that type of security constraint applies to all requests that match the URL patterns in the web resource collection and not just to the login dialog box.

    Moreover, I suppose that the port 8443 is not available because you do not have Tomcat configured to use SSL.
    At the following link you can find a nice how-to about configuring SSL support on Tomcat:

    Apache Tomcat 7. SSL/TLS Configuration HOW-TO

    --- EDIT (server.xml config was posted) ---

    To be redirected to port 8443 you need to change the connector configuration as shown below:

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

    Apache Tomcat 7. The AJP Connector

    redirectPort

    If this Connector is supporting non-SSL requests, and a request is received for which a matching security-constraint requires SSL transport, Catalina will automatically redirect the request to the port number specified here.