Resolving AJP Connector Configuration Errors After Spring Boot 2.2.5 Upgrade: Analysis and Secure Practices

Dec 11, 2025 · Programming · 11 views · 7.8

Keywords: Spring Boot | AJP Connector | Tomcat Security Configuration

Abstract: This technical article provides an in-depth analysis of the AJP connector configuration error that occurs when upgrading Spring Boot from version 2.1.9 to 2.2.5. The error stems from Tomcat 9.0.31's enhanced security requirements for the AJP protocol, mandating a non-empty secret when secretRequired is set to true. Based on the best practice solution, the article details how to properly configure the AJP connector in Spring Boot, including programmatically setting the secretRequired property, configuring connector parameters, and understanding associated security risks. Complete code examples and configuration instructions are provided, along with comparisons of alternative approaches, helping developers resolve upgrade compatibility issues while maintaining system security.

Problem Context and Error Analysis

During the upgrade from Spring Boot 2.1.9 to 2.2.5, many developers encounter the following runtime error:

Caused by: java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.
   at org.apache.coyote.ajp.AbstractAjpProtocol.start(AbstractAjpProtocol.java:264)
   at org.apache.catalina.connector.Connector.startInternal(Connector.java:1035)
   ... 22 common frames omitted

The root cause of this error is that Spring Boot 2.2.5 bundles Tomcat 9.0.31 by default, which includes security enhancements addressing the Ghostcat vulnerability (CVE-2020-1938). The AJP (Apache JServ Protocol), used for communication between Tomcat and web servers like Apache HTTP Server, had security flaws in earlier versions that allowed attackers to read or include arbitrary files on the server.

Security Improvements in Tomcat 9.0.31

Tomcat 9.0.31 introduces a crucial security mechanism: when the AJP connector's secretRequired property is set to true, a non-empty secret property must also be configured. This design forces developers to explicitly choose the security level for AJP connections: either authenticate via a secret key or explicitly disable the secret requirement while accepting the associated security risks.

In Spring Boot's auto-configuration, if developers enable the AJP connector without explicitly setting the secretRequired property, the system may use the default value true while keeping the secret property empty, triggering the aforementioned exception. This reflects Tomcat's strict approach to security—ambiguous security configurations are not permitted.

Solution Implementation

Based on best practices, we recommend programmatically configuring the AJP connector with all relevant parameters explicitly set. Below is a complete configuration class example:

package com.example.config;

import org.apache.catalina.connector.Connector;
import org.apache.coyote.ajp.AbstractAjpProtocol;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TomcatConfiguration {

    @Value("${tomcat.ajp.port}")
    int ajpPort;

    @Value("${tomcat.ajp.remoteauthentication}")
    String remoteAuthentication;

    @Value("${tomcat.ajp.enabled}")
    boolean tomcatAjpEnabled;

    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        if (tomcatAjpEnabled) {
            Connector ajpConnector = new Connector("AJP/1.3");
            ajpConnector.setPort(ajpPort);
            ajpConnector.setSecure(false);
            ajpConnector.setAllowTrace(false);
            ajpConnector.setScheme("http");
            ((AbstractAjpProtocol) ajpConnector.getProtocolHandler()).setSecretRequired(false);
            tomcat.addAdditionalTomcatConnectors(ajpConnector);
        }
        return tomcat;
    }
}

Key configuration analysis:

  1. Connector Type: Use "AJP/1.3" to specify the protocol version, which is the standard AJP protocol currently supported by Tomcat.
  2. Port Configuration: Set the AJP listening port via ajpConnector.setPort(ajpPort), typically using non-standard HTTP ports like 9090.
  3. Security Settings: setSecure(false) indicates that the connection does not use SSL/TLS encryption, as the AJP protocol is designed for trusted networks.
  4. Core Fix: ((AbstractAjpProtocol) ajpConnector.getProtocolHandler()).setSecretRequired(false) explicitly sets the secret requirement to false, which is the key operation to resolve the upgrade error.

Corresponding application.properties configuration:

server.port=8082
tomcat.ajp.port=9090
tomcat.ajp.remoteauthentication=false
tomcat.ajp.enabled=true

Comparison of Alternative Approaches

In community discussions, developers have proposed various solutions, each with its pros and cons:

Approach 1: Directly Modify server.xml (Not Recommended)

<Connector protocol="AJP/1.3" address="::1" port="8009"
           redirectPort="8443" secretRequired="false" />

This method directly modifies Tomcat's configuration file. It is simple but has significant drawbacks: first, it bypasses Spring Boot's configuration management, leading to scattered configurations; second, setting secretRequired to false without other security measures may reintroduce Ghostcat vulnerability risks.

Approach 2: Use Secret Protection (Security Recommended)

@Configuration
public class TomcatConfig {
    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        Connector ajpConnector = new Connector("org.apache.coyote.ajp.AjpNioProtocol");
        AjpNioProtocol protocol = (AjpNioProtocol) ajpConnector.getProtocolHandler();
        protocol.setSecret("myapjsecret");
        ajpConnector.setPort(9090);
        ajpConnector.setSecure(true);
        tomcat.addAdditionalTomcatConnectors(ajpConnector);
        return tomcat;
    }
}

This is the most secure solution. It sets a shared secret via protocol.setSecret("myapjsecret"), ensuring only clients with the secret can establish AJP connections. Additionally, setSecure(true) enables transport layer security. This approach aligns with Tomcat's security recommendations but requires coordinating with front-end web servers (e.g., Apache) to use the same secret.

Security Considerations and Best Practices

Regardless of the chosen approach, understanding the security implications is essential:

  1. Network Isolation: The AJP protocol is designed for trusted networks and must never be exposed to the internet. Firewall rules must restrict access to the AJP port to specific front-end servers only.
  2. Secret Management: If using the secret-based approach, establish secure secret distribution and rotation mechanisms to prevent leaks.
  3. Monitoring and Auditing: After enabling AJP connections, enhance monitoring of related ports to detect abnormal connection attempts.
  4. Alternative Solutions: Consider whether AJP is truly necessary. In modern deployments, many scenarios can achieve similar functionality via HTTP/HTTPS reverse proxies, avoiding the special protocol of AJP.

Conclusion

The AJP configuration error triggered by the Spring Boot 2.2.5 upgrade is fundamentally a result of Tomcat's security enhancements, not a software defect. Developers should view this as an opportunity to improve their system's security configuration. The recommended practice is: first, assess the necessity of the AJP protocol; if it is required, prioritize the secret protection approach; if disabling the secret requirement is chosen, ensure strict network access controls are in place. The configuration solution provided in this article resolves compatibility issues while maintaining centralized configuration management and maintainability, suitable for most Spring Boot application scenarios.

By properly addressing this configuration issue, developers can not only successfully upgrade to Spring Boot 2.2.5 and Tomcat 9.0.31 but also enhance the overall security of their applications, protecting against protocol-layer vulnerabilities like Ghostcat.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.