使用 http2 的 Jetty ssl 工厂不起作用
Jetty ssl factory using http2 doesn't work
我有一个使用 jetty 的简单 spring 启动项目。
我 运行 在端口 443 上使用 http1.1 就好了
@Bean(name = "containerCustomizer")
public WebServerFactoryCustomizer containerCustomizer()
{
return (container -> ((JettyServletWebServerFactory) container).addServerCustomizers(server -> {
// HTTPS
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStoreResource(Resource.newResource(
getClass().getClassLoader().getResource("keystore.jks")));
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setProtocol("TLS");
sslContextFactory.setKeyStoreType("JKS");
HttpConfiguration https = new HttpConfiguration();
https.addCustomizer(new SecureRequestCustomizer());
SslConnectionFactory sslFactory = new SslConnectionFactory(sslContextFactory,
HttpVersion.HTTP_1_1.asString());
ServerConnector sslConnector = new ServerConnector(server, sslFactory, new HttpConnectionFactory(https));
sslConnector.setPort(443);
server.setConnectors(new Connector[] {sslConnector});
}));
}
然而,一旦我通过将 HttpVersion.HTTP_1_1.asString()
替换为 HttpVersion.HTTP_2.asString()
更改为 HTTP2,我就会得到异常
Caused by: java.lang.IllegalStateException: No protocol factory for SSL next protocol: 'HTTP/2.0' in ServerConnector@61e45f87{SSL, (ssl, http/1.1)}{0.0.0.0:443}
at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:317) ~[jetty-server-9.4.35.v20201120.jar:9.4.35.v20201120]
at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:81) ~[jetty-server-9.4.35.v20201120.jar:9.4.35.v20201120]
at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:234) ~[jetty-server-9.4.35.v20201120.jar:9.4.35.v20201120]
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73) ~[jetty-util-9.4.35.v20201120.jar:9.4.35.v20201120]
at org.springframework.boot.web.embedded.jetty.JettyWebServer.start(JettyWebServer.java:174) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
... 16 common frames omitted
仅更改版本字符串是不够的。
您还需要...
ALPNServerConnectionFactory
- 用于处理选择 HTTP/2 协议的 TLS 层(称为 ALPN)
HTTP2ServerConnectionFactory
- 使用 HTTP/2 协议
如 embedded / Http2Server.java example
中所见
关键是您将连接类型链接在一起,ALPN 到 HTTP2 到 HTTPS。
// SSL Context Factory for HTTPS and HTTP/2
SslContextFactory sslContextFactory = new SslContextFactory.Server();
// configure sslContextFactory
// HTTPS Configuration
HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
httpsConfig.addCustomizer(new SecureRequestCustomizer());
// HTTP/2 Connection Factory
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig);
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
alpn.setDefaultProtocol(http.getDefaultProtocol());
// SSL Connection Factory
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol());
// HTTP/2 Connector
ServerConnector http2Connector =
new ServerConnector(server, ssl, alpn, h2, new HttpConnectionFactory(httpsConfig));
http2Connector.setPort(securePort);
server.addConnector(http2Connector);
我有一个使用 jetty 的简单 spring 启动项目。
我 运行 在端口 443 上使用 http1.1 就好了
@Bean(name = "containerCustomizer")
public WebServerFactoryCustomizer containerCustomizer()
{
return (container -> ((JettyServletWebServerFactory) container).addServerCustomizers(server -> {
// HTTPS
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStoreResource(Resource.newResource(
getClass().getClassLoader().getResource("keystore.jks")));
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setProtocol("TLS");
sslContextFactory.setKeyStoreType("JKS");
HttpConfiguration https = new HttpConfiguration();
https.addCustomizer(new SecureRequestCustomizer());
SslConnectionFactory sslFactory = new SslConnectionFactory(sslContextFactory,
HttpVersion.HTTP_1_1.asString());
ServerConnector sslConnector = new ServerConnector(server, sslFactory, new HttpConnectionFactory(https));
sslConnector.setPort(443);
server.setConnectors(new Connector[] {sslConnector});
}));
}
然而,一旦我通过将 HttpVersion.HTTP_1_1.asString()
替换为 HttpVersion.HTTP_2.asString()
更改为 HTTP2,我就会得到异常
Caused by: java.lang.IllegalStateException: No protocol factory for SSL next protocol: 'HTTP/2.0' in ServerConnector@61e45f87{SSL, (ssl, http/1.1)}{0.0.0.0:443}
at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:317) ~[jetty-server-9.4.35.v20201120.jar:9.4.35.v20201120]
at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:81) ~[jetty-server-9.4.35.v20201120.jar:9.4.35.v20201120]
at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:234) ~[jetty-server-9.4.35.v20201120.jar:9.4.35.v20201120]
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73) ~[jetty-util-9.4.35.v20201120.jar:9.4.35.v20201120]
at org.springframework.boot.web.embedded.jetty.JettyWebServer.start(JettyWebServer.java:174) ~[spring-boot-2.3.7.RELEASE.jar:2.3.7.RELEASE]
... 16 common frames omitted
仅更改版本字符串是不够的。
您还需要...
ALPNServerConnectionFactory
- 用于处理选择 HTTP/2 协议的 TLS 层(称为 ALPN)HTTP2ServerConnectionFactory
- 使用 HTTP/2 协议
如 embedded / Http2Server.java example
中所见关键是您将连接类型链接在一起,ALPN 到 HTTP2 到 HTTPS。
// SSL Context Factory for HTTPS and HTTP/2
SslContextFactory sslContextFactory = new SslContextFactory.Server();
// configure sslContextFactory
// HTTPS Configuration
HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
httpsConfig.addCustomizer(new SecureRequestCustomizer());
// HTTP/2 Connection Factory
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig);
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
alpn.setDefaultProtocol(http.getDefaultProtocol());
// SSL Connection Factory
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol());
// HTTP/2 Connector
ServerConnector http2Connector =
new ServerConnector(server, ssl, alpn, h2, new HttpConnectionFactory(httpsConfig));
http2Connector.setPort(securePort);
server.addConnector(http2Connector);