Apache 无法连接到新的 tomcat 9 ajp

Ami*_*nos 4 apache tomcat spring-boot

将 Spring boot 的版本从 2.1.4 升级到 2.3.2 后,我的 apache2 无法再(通过 ajp)连接到我的 Spring boot 的嵌入式 tomcat。

它显示以下错误:

[proxy:error] [pid xxxx ] (111)Connection refused: AH00957: AJP: attempt to connect to 10.0.75.1:8500 (10.0.75.1) failed
[proxy_ajp:error] [pid xxxx ] [client xxx ] AH00896: failed to make connection to backend: 10.0.75.1, referer: http://myapp.develop/home/
Run Code Online (Sandbox Code Playgroud)

我的开发环境是这样设置的:

  • 一个 Angular 应用程序(运行在 4200 上的节点服务器)

  • Spring Boot 后端(在 8500 端口上的 tomcat 上设置的 ajp 连接器)

  • 前端 apache2 服务器(在 docker 容器上)设置为将请求重定向到两个应用程序:

    <VirtualHost *:80>
    ServerName myapp.develop
    
    ProxyPass "/home" "http://10.0.75.1:4200/home"
    ProxyPassReverse "/home" "http://10.0.75.1:4200/home"
    
    ProxyPass "/backend" "ajp://10.0.75.1:8500/backend"
    ProxyPassReverse "/backend" "ajp://10.0.75.1:8500/backend"
    
    Run Code Online (Sandbox Code Playgroud)

我通过 /etc/hosts 上的域名访问我的网络应用程序:myapp.develop

这是我的spring boot tomcat的配置

   Connector connector = new Connector("AJP/1.3");
   connector.setScheme("http");
   connector.setPort(8500);
   connector.setSecure(false);
   connector.setAllowTrace(false);
   ((AbstractAjpProtocol) connector.getProtocolHandler()).setSecretRequired(false);
Run Code Online (Sandbox Code Playgroud)

在 app.properties 中:

tomcat.ajp.port=8500
tomcat.ajp.remoteauthentication=false
tomcat.ajp.enabled=true
Run Code Online (Sandbox Code Playgroud)

这是 tomcat 日志:

o.s.b.w.e.t.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http) 8500 (http)
o.a.c.h.Http11NioProtocol    : Initializing ProtocolHandler ["http-nio-8080"]
o.a.c.a.AjpNioProtocol       : Initializing ProtocolHandler ["ajp-nio-127.0.0.1-8500"]
o.a.c.c.StandardService      : Starting service [Tomcat]
o.a.c.c.StandardEngine       : Starting Servlet engine: [Apache Tomcat/9.0.37]
Run Code Online (Sandbox Code Playgroud)

我怀疑这种变化:

  • 从 8.5.51 开始,AJP 连接器的默认监听地址改为环回地址而不是所有地址。

是什么导致了我这个问题,但我不知道如何解决它。

小智 5

我在升级 tomcat 版本时遇到了类似的问题。将下面提到的属性添加到 ajp 连接器有助于我的情况。

connector.setProperty("address","0.0.0.0");
connector.setProperty("allowedRequestAttributesPattern",".*");
((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);
Run Code Online (Sandbox Code Playgroud)

详细说明:

对于你的疑问:

从 8.5.51 开始,AJP 连接器的默认监听地址改为环回地址而不是所有地址。

在此更新之前,tomcat AJP 连接器愿意接受来自任何 IP 地址的请求,因此不需要明确指定“地址”属性。但是在此更新之后,默认行为是 AJP 连接器愿意接受仅作为 localhost(环回)发出的请求。使用下面列出的“地址”属性将侦听范围扩展到不仅是环回地址

connector.setProperty("address","0.0.0.0"); // OR connector.setProperty("address","::");
Run Code Online (Sandbox Code Playgroud)

使用以下属性启用所有类型的请求属性(除非您有标头信息,在这种情况下启用特定的)。具有无法识别的请求属性的请求将被拒绝并返回 403 响应:

connector.setProperty("allowedRequestAttributesPattern",".*"); 
Run Code Online (Sandbox Code Playgroud)

使用“secretRequired”属性来定义是否需要与 HTTP 服务器交换机密以允许通过 ajp 的请求。如果是,则还要设置“secret”属性。否则请求将失败并显示 403。

((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);
Run Code Online (Sandbox Code Playgroud)

参考:Apache Tomcat 8 配置参考

使用 AJP 协议需要额外的安全考虑,因为与 HTTP 连接器相比,它允许对 Tomcat 的内部数据结构进行更多的直接操作。应特别注意用于addresssecretsecretRequiredallowedRequestAttributesPattern属性的值。


Ola*_*ock 2

我从未见过在这样的代码中设置连接器,而是在 server.xml 中声明它

然而,你的代码是

Connector connector = new Connector("AJP/1.3");
connector.setScheme("http");
connector.setPort(8500);
connector.setSecure(false);
connector.setAllowTrace(false);
((AbstractAjpProtocol) connector.getProtocolHandler()).setSecretRequired(false);
Run Code Online (Sandbox Code Playgroud)

然后你声明你知道这个重大变化

从 8.5.51 开始,AJP Connector 的默认监听地址已更改为环回地址而不是所有地址。

结合两者:您从未在代码中设置监听地址 - 因此您可能使用默认值。当您尝试转发到非环回地址时,将无法以这种方式到达服务器。

这个答案的匿名编辑建议connector.setAttribute("address", "0.0.0.0");,但就我个人而言,我更愿意将其保留在 server.xml 中:连接器通常不会在运行时配置和更改,并且让管理员编辑文本文件在日常工作中更加方便- 日常运营。