仅使用 HTTPS 的 Jetty 9.3 SSL-ALPN-HTTP2 错误 ERR_EMPTY_RESPONSE

Jetty 9.3 SSL-ALPN-HTTP2 error ERR_EMPTY_RESPONSE with HTTPS only

我已经将 Jetty 9.2 HTTP/1.1 + 仅 SSL 服务器(嵌入式)升级到 Jetty 9.3.0 (v20150612) HTTP/HTTPS 2.0 (SLL(TLS)-ALPN-HTTP/2 ).我使用 JRE 8(Oracle 1.8.0 Build 45 - b15)和 Eclipse。

* JOAKIM 的回答解决了问题:参见 post 末尾的解决方案 *

在升级之前,HTTP 和 HTTPS 工作正常,它仍然可以通过简单地使用 Jetty 9.3 Jar 文件重建。然后我升级了代码(从我设法找到的示例中学习)以合并 SSL(TLS)-ALPN-HTTP/2-HTTP/1.1。我使用的主要例子是 in this link with code

A Google Chrome (版本 43.0.2357.130 m) 浏览器可以正常处理 http 请求,例如 http:// 10.32.1.110:8080/ 并显示网页。但是,如果我打开第二个选项卡并尝试 https://10.32.1.110:8443/,我会收到一个错误 ERR_EMPTY_RESPONSE。但是,我可以连接到 webtide.com 并获得 https 会话。已排除防火墙对我系统的干扰。 10.32.???对于失败的 HTTPS,工作 HTTP 的连接也没有传递它。

此错误不会阻止 Jetty 服务器(服务器不会抛出或记录错误),我可以返回到第一个浏览器选项卡并继续请求网页,我看到它已更新(我有一个时间戳和计数器)每次。

在 HTTPS 的情况下,我的 handle() 方法没有被 Jetty 调用(我有一个日志行来监控它),我看到 handle() 方法中只有 HTTP 请求。根据 Jetty 请求对象,确实到达我的 handle() 的 http 请求属于 HTTP/1.1 类型。根据我的研究,这是正常的,因为 Google Chrome 没有 SSL/ALPN 就不会 HTTP/2。

我一直在思考 SSL 和 ALPN 问题的方向,因为 HTTPS 请求导致 ERR_EMPTY_RESPONSE。 alpn-api-1.1.2.v20150522.jar 作为“-Xbootclasspath/p:D:\Users\TWO\DATA\Eclipse\alpn-api-1.1.2 添加到我的 Eclipse VM 参数(相当于 JVM 引导类路径)。 v20150522\alpn-api-1.1.2.v20150522.jar" 从那时起,Jetty 不再抱怨 ALPN 不在 JVM 引导类路径上(通过像以前一样抛出错误)。从下面的 Jetty 日志中,SLL 和 HTTP/2 也已正确启动。

Jetty 服务器正常启动并显示这些日志:

2015-06-24 15:53:29.292:INFO:oejs.Server:main: jetty-9.3.0.v20150612
2015-06-24 15:53:29.323:INFO:oejs.ServerConnector:main: Started ServerConnector@123772c4{HTTP/1.1,[http/1.1, h2c, h2c-17, h2c-16, h2c-15, h2c-14]}{0.0.0.0:8080}
2015-06-24 15:53:29.338:INFO:oejus.SslContextFactory:main: x509={jetty.eclipse.org=jetty} wild={} alias=null for SslContextFactory@6f75e721(file:///D:/Users/[removed]/keystores/keystore,file:///D:/Users/[removed]/keystores/keystore)
2015-06-24 15:53:29.495:INFO:oejs.ServerConnector:main: Started ServerConnector@13deb50e{SSL,[ssl, alpn, h2, h2-17, h2-16, h2-15, h2-14, http/1.1]}{0.0.0.0:8443}
2015-06-24 15:53:29.495:INFO:oejs.Server:main: Started @321ms

这里是相关的Java服务器代码:

... standard Jetty imports plus
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
import org.eclipse.jetty.http2.HTTP2Cipher;
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;


QueuedThreadPool oTP = new QueuedThreadPool(20);
this.oServer = new Server(oTP);
this.oServer.setHandler((Handler) this);

HttpConfiguration httpcfg = new HttpConfiguration();
httpcfg.setSecureScheme("https");
httpcfg.setSecurePort(8443);

HttpConnectionFactory httpF=new HttpConnectionFactory(httpcfg);
HTTP2CServerConnectionFactory http2F=new HTTP2CServerConnectionFactory(httpcfg);

ServerConnector http=new ServerConnector(this.oServer,httpF,http2F);
http.setPort(8080);
this.oServer.addConnector(http);

SslContextFactory sslCF=new SslContextFactory();
sslCF.setKeyStorePath(MetaWebServerConfig.getWebServerKeystore()+"keystore"); 
sslCF.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslCF.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
sslCF.setTrustStorePath(MetaWebServerConfig.getWebServerKeystore()+"keystore"); 
sslCF.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");

sslCF.setExcludeCipherSuites(
              "SSL_RSA_WITH_DES_CBC_SHA",
              "SSL_DHE_RSA_WITH_DES_CBC_SHA",
              "SSL_DHE_DSS_WITH_DES_CBC_SHA",
              "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
              "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
              "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
              "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");

sslCF.setCipherComparator(new HTTP2Cipher.CipherComparator());

HttpConfiguration httpscfg = new HttpConfiguration(httpcfg);
httpscfg.addCustomizer(new SecureRequestCustomizer());

HTTP2ServerConnectionFactory h2F=new HTTP2ServerConnectionFactory(httpscfg);

NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable();
ALPNServerConnectionFactory alpnF=new ALPNServerConnectionFactory();
alpnF.setDefaultProtocol(http.getDefaultProtocol());

SslConnectionFactory sslF=new SslConnectionFactory(sslCF,alpnF.getProtocol());
HttpConnectionFactory https2F=new HttpConnectionFactory(httpscfg);

ServerConnector http2=new ServerConnector(this.oServer,sslF,alpnF,h2F,https2F);
http2.setPort(8443);
this.oServer.addConnector(http2);

ALPN.debug=false;
this.oServer.start();

应 gregw 的要求,我尝试了顶部 link 中的示例代码。我只修改了 SslContextFactory 的密钥库路径。我总是使用相同的密钥库文件,因为我知道它没问题(请参阅 post 的开头 - 我的旧 HTTP/1.1+SLL 工作并使用相同的密钥库。

2015-06-25 14:07:14.972:INFO:oejs.Server:main: jetty-9.3.0.v20150612
2015-06-25 14:07:15.019:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@6f75e721{/,file:///D:/Users/[path]/docroot,AVAILABLE}
2015-06-25 14:07:15.082:INFO:oejs.ServerConnector:main: Started ServerConnector@1888ff2c{HTTP/1.1,[http/1.1, h2c, h2c-17, h2c-16, h2c-15, h2c-14]}{0.0.0.0:8080}
2015-06-25 14:07:15.097:INFO:oejus.SslContextFactory:main: x509={jetty.eclipse.org=jetty} wild={} alias=null for SslContextFactory@4b952a2d(file:///D:/Users/[path]/keystores/keystore,null)
2015-06-25 14:07:15.269:INFO:oejs.ServerConnector:main: Started ServerConnector@5594a1b5{SSL,[ssl, alpn, h2, h2-17, h2-16, h2-15, h2-14, http/1.1]}{0.0.0.0:8443}
2015-06-25 14:07:15.269:INFO:oejs.Server:main: Started @587ms

使用 http 访问有效,但使用 https 无效,浏览器再次显示 ERR_EMPTY_RESPONSE。

尝试使用 IExplorer 11。结果相同。适用于 http,不适用于 https(msg = This page can't be displayed)不要与 404(无法找到此页面)混淆。与 Chrome 相反,当 greg 的代码与 http 一起使用但没有与 https 一起使用时,IE 确实给出了 'Cookie' 警告。

有没有人知道如何解决上述问题。 TIA

* 解决方案 *

按照 Joakim 的建议,我将 alpn-boot-8.1.3.v20150130.jar 添加到引导类路径中,而不是 alpn-api-1.1.2.v20150522.jar .测试导致以下组合完美运行:

这些是我唯一感兴趣的未来组合,尽管我确信 HTTP/2_0 和 SSL 也可以工作。

Jetty Documentation link 显示 JRE 版本和 ALPN JAR 文件版本之间的 table,以防另一个 JRE 出现相同问题。

非常感谢所有试图帮助解决此问题的人。

对于Oracle/OpenJDK Java JRE/JDK 你使用alpn-boot.jar,而不是alpn-api.jar ...

  • 对于Java 1.8.0_25,你使用alpn-boot-8.1.2.v20141202.jar
  • 对于Java 1.8.0_45,你使用alpn-boot-8.1.3.v20150130.jar

请参阅 ALPN / Versions 文档以了解 table 的 Java 到 alpn-boot 版本。

这非常重要,因为这会修改 Java 本身的 SSL/TLS 层,以添加对 HTTP/2 运行所需的 ALPN 协议的支持。

此 -Xbootclasspath 要求是强制性的,直到将来 Java 附带内置 ALPN(计划于 Java 9)