在将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/
我的开发环境是这样设置的:
Angular应用程序(运行在4200上的节点服务器(
一个弹簧引导后端(在tomcat上8500端口上设置的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"
我通过/etc/hosts上的域名访问我的web应用程序:myapp.develope
这是我的春靴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);
在app.properties:中
tomcat.ajp.port=8500
tomcat.ajp.remoteauthentication=false
tomcat.ajp.enabled=true
这是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]
我怀疑这种变化:
- 在8.5.51以后的版本中,AJP连接器的默认侦听地址被更改为环回地址,而不是所有地址
是造成我这个问题的原因,但我不知道如何解决它。
我在升级tomcat版本时遇到了类似的问题。将下面提到的属性添加到ajp连接器帮助了我的案例。
connector.setProperty("address","0.0.0.0");
connector.setProperty("allowedRequestAttributesPattern",".*");
((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);
详细说明:
对于您的疑问:
在8.5.51以后的版本中,AJP连接器的默认侦听地址为更改为环回地址,而不是所有地址。
在此更新之前,tomcat AJP连接器愿意接受来自任何IP地址的请求,因此不需要显式指定";地址";所有物但在这次更新之后,默认行为是AJP连接器愿意接受仅作为localhost(环回(发出的请求。使用下面列出的";地址";属性以将侦听范围扩展到不仅环回地址
connector.setProperty("address","0.0.0.0"); // OR connector.setProperty("address","::");
使用以下属性可以启用所有类型的请求属性(除非您有标头信息,否则请启用特定的请求属性(。具有无法识别的请求属性的请求将被403响应拒绝:
connector.setProperty("allowedRequestAttributesPattern",".*");
使用";secretRequired";属性来定义是否需要与HTTP服务器交换机密,以便允许通过ajp进行请求。如果是,则设置"是";秘密";属性。否则,请求将以403失败。
((AbstractAjpProtocol)connector.getProtocolHandler()).setSecretRequired(false);
参考:Apache Tomcat 8配置参考
AJP协议的使用需要额外的安全考虑因为它允许更直接地操作Tomcat的内部数据结构而不是HTTP连接器。应特别注意支付给地址、机密和secretRequired使用的值allowedRequestAttributesPattern属性。
我从未见过在这样的代码中设置连接器,它是在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);
然后你声明你知道这个突破性的改变
在8.5.51以后的版本中,AJP连接器的默认侦听地址被更改为环回地址,而不是所有地址。
两者结合:您从未在代码中设置侦听地址,因此您可能使用默认地址。当你试图转发到一个非环回地址时,没有办法通过这种方式到达服务器。
这个答案的一位匿名编辑器建议使用connector.setAttribute("address", "0.0.0.0");
,但就我个人而言,我更喜欢将其保存在server.xml中:连接器通常不会在运行时进行配置和更改,让管理员编辑文本文件在日常操作中会方便得多。