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.
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.
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.
The AJP Connector element represents a Connector component that communicates with a web connector via the AJP protocol.
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.
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;
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With