Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 620
tomas Avatar asked Mar 14 '18 10:03

tomas


People also ask

Is Ajp better than HTTP?

HTTP connectors can also be used as part of a load balancing scheme, in conjunction with an HTTP load balancer that supports session stickiness, such as mod_proxy. However, as AJP tends to handle proxying better than HTTP, this usage is not common.

How do I know if my AJP connector is enabled?

The most common way to identify whether the protocol is indeed enabled is to first locate the web server's conf/ directory. Look for the server. xml configuration file that specifies all the default protocols and the document root directory configuration.

What is AJP connector Tomcat 9?

The AJP Connector element represents a Connector component that communicates with a web connector via the AJP protocol.

What is Ajp in Java?

The Apache JServ Protocol (AJP) is a binary protocol that can proxy inbound requests from a web server through to an application server that sits behind the web server.


2 Answers

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;
    }
like image 131
tomas Avatar answered Sep 20 '22 18:09

tomas


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

like image 30
Matze Avatar answered Sep 19 '22 18:09

Matze