tomas
tomas

Reputation: 840

Spring Boot 2 - AJP

I added an connector for AJP to my spring boot 2 project

 @Bean
 public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new 
   TomcatServletWebServerFactory() {
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint securityConstraint = new SecurityConstraint();
                securityConstraint.setUserConstraint("CONFIDENTIAL");
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                securityConstraint.addCollection(collection);
                context.addConstraint(securityConstraint);
            }
        };
        tomcat.addAdditionalTomcatConnectors(redirectConnector());

        return tomcat;
    }

    private Connector redirectConnector() {
        Connector connector = new Connector("AJP/1.3");
        connector.setScheme("http");
        connector.setPort(ajpPort);
        connector.setSecure(false);
        connector.setAllowTrace(false);
        return connector;
    }

This works fine. I can now access my spring boot application over my apache webserver. But now if i run my spring boot application i can not do access my spring boot application directly. So this url doesn't work anymore

http://localhost:13080/online/showlogin?m=test

If i disable the AJP Connector the URL works again. I have tried the following

 private Connector redirectConnector2() {
    Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
    connector.setScheme("http");
    connector.setPort(13080);
    connector.setSecure(false);
    connector.setAllowTrace(false);
    return connector;
}
...
tomcat.addAdditionalTomcatConnectors(redirectConnector2());
...

But this does not help me.

Upvotes: 8

Views: 13065

Answers (2)

Matze
Matze

Reputation: 401

We used the code of tomas answers for a longer time successfully but it stopped working after we had upgraded to a Spring Boot version > 2.2.4. We got this error message on startup:

APPLICATION FAILED TO START

Description:

The Tomcat connector configured to listen on port 1234 failed to start. The port may already be in use or the connector may be misconfigured.

Action:

Verify the connector's configuration, identify and stop any process that's listening on port 1234, or configure this application to listen on another port.

But the port was not used, so what was the problem?

The issue was caused by the fix for the Ghostcat vulnerability of AJP in Tomcat that was included in Spring Boot 2.2.5.

Now you have two options, either you use AJP with a secret:

final Connector connector = new Connector("AJP/1.3");
connector.setScheme("http");
connector.setPort(ajpPort);
connector.setAllowTrace(false);

final AbstractAjpProtocol protocol = (AbstractAjpProtocol) connector.getProtocolHandler();
connector.setSecure(true);
protocol.setSecret(ajpSecret);

or without one, but for that you have to explicitly set setSecretRequired to false:

final Connector connector = new Connector("AJP/1.3");
connector.setScheme("http");
connector.setPort(ajpPort);
connector.setAllowTrace(false);

final AbstractAjpProtocol protocol = (AbstractAjpProtocol) connector.getProtocolHandler();
connector.setSecure(false);
protocol.setSecretRequired(false);

Note: The later solution will make your tomcat vulnerable to Ghostcat again.

For more information have a look at this thread: Springboot -The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "" after upgrade to 2.2.5

Upvotes: 7

tomas
tomas

Reputation: 840

This works for me:

    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainer() {
      return server -> {
        if (server instanceof TomcatServletWebServerFactory) {
            ((TomcatServletWebServerFactory) server).addAdditionalTomcatConnectors(redirectConnector());
        }
      };
    }

    private Connector redirectConnector() {
       Connector connector = new Connector("AJP/1.3");
       connector.setScheme("http");
       connector.setPort(ajpPort);
       connector.setSecure(false);
       connector.setAllowTrace(false);
       return connector;
    }

Upvotes: 14

Related Questions