无法使用 Grizzly 2.3.19 在 HTTPS 服务器上使用 SNI 过滤器
Can't use SNI filter on HTTPS server with Grizzly 2.3.19
我正在尝试做一个客户端 SNI 应用程序,为了进行集成测试,我正在使用 Grizzly 服务器来测试 SNI 是否通过。我按照 docs 使用过滤器。但是过滤器永远不会被调用。
文档未显示完整示例。我发现添加过滤器的机制似乎被忽略了。 2.2 中使用的旧方法不再是public。
以下是我的代码:
private TCPNIOTransport createMockServerTransport() {
final SSLEngineConfigurator sslServerEngineConfig = new SSLEngineConfigurator(createSSLContextConfigurator().createSSLContext(), false, false, false);
return TCPNIOTransportBuilder.newInstance().setProcessor(getFilters()).build();
}
private FilterChain getFilters() {
SNIFilter sniFilter = getSniFilter();
final FilterChain chain = FilterChainBuilder.stateless()
.add(new TransportFilter())
.add(sniFilter)
.add(new StringFilter())
.add(new BaseFilter() {
@Override
public NextAction handleRead(final FilterChainContext ctx)
throws IOException {
return ctx.getInvokeAction();
}
})
.build();
return chain;
}
private SNIFilter getSniFilter() {
final Attribute<String> sniHostAttr = Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("sni-host-attr");
SNIFilter sniFilter = new SNIFilter();
sniFilter.setServerSSLConfigResolver(new SNIServerConfigResolver() {
@Override
public SNIConfig resolve(Connection connection, String hostname) {
sniHostAttr.set(connection, hostname);
if (StringUtils.isEmpty(hostname)) {
throw new IllegalArgumentException("SNI Has not been sent");
}
return SNIConfig.newServerConfig(sslServerEngineConfig);
}
});
return sniFilter;
}
private SSLContextConfigurator createSSLContextConfigurator() {
SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();
ClassLoader cl = HttpRequestSNITestCase.class.getClassLoader();
URL cacertsUrl = cl.getResource("trustStore");
if (cacertsUrl != null) {
sslContextConfigurator.setTrustStoreFile(cacertsUrl.getFile());
sslContextConfigurator.setTrustStorePass("myPassword");
}
URL keystoreUrl = cl.getResource("serverKeystore");
if (cacertsUrl != null) {
sslContextConfigurator.setKeyStoreFile(keystoreUrl.getFile());
sslContextConfigurator.setKeyStorePass("myPassword");
sslContextConfigurator.setKeyPass("myPassword");
}
return sslContextConfigurator;
}
public class Server {
private HttpServer webServer;
protected void startServer() throws IOException {
SSLEngineConfigurator sslServerEngineConfig = new SSLEngineConfigurator(createSSLContextConfigurator().createSSLContext(), false, false, false);
NetworkListener networkListener = new NetworkListener("sample-listener", "localhost", httpsPort.getNumber());
networkListener.setTransport(createMockServerTransport());
networkListener.setSSLEngineConfig(sslServerEngineConfig);
webServer = HttpServer.createSimpleServer();
webServer.addListener(networkListener);
networkListener.setSecure(true);
networkListener.getTransport().setProcessor(getFilters());
FilterChain chain = networkListener.getFilterChain();
webServer.start();
}
protected void stopServer() {
webServer.shutdownNow();
}
}
为了更新 HttpServer 过滤器链,您必须使用 AddOn:
protected void startServer() throws IOException {
NetworkListener networkListener = new NetworkListener("sample-listener", "localhost", 8081);
sslServerEngineConfig = new SSLEngineConfigurator(createSSLContextConfigurator().createSSLContext(), false, false, false);
networkListener.setSSLEngineConfig(sslServerEngineConfig);
networkListener.setSecure(true);
networkListener.registerAddOn(new SniAddOn());
webServer = HttpServer.createSimpleServer();
webServer.addListener(networkListener);
webServer.start();
}
private class SniAddOn implements AddOn {
public void setup(NetworkListener networkListener,
FilterChainBuilder builder) {
// replace SSLFilter (if any) with SNIFilter
final int idx = builder.indexOfType(SSLBaseFilter.class);
if (idx != -1) {
builder.set(idx, getSniFilter());
}
}
}
我正在尝试做一个客户端 SNI 应用程序,为了进行集成测试,我正在使用 Grizzly 服务器来测试 SNI 是否通过。我按照 docs 使用过滤器。但是过滤器永远不会被调用。
文档未显示完整示例。我发现添加过滤器的机制似乎被忽略了。 2.2 中使用的旧方法不再是public。
以下是我的代码:
private TCPNIOTransport createMockServerTransport() {
final SSLEngineConfigurator sslServerEngineConfig = new SSLEngineConfigurator(createSSLContextConfigurator().createSSLContext(), false, false, false);
return TCPNIOTransportBuilder.newInstance().setProcessor(getFilters()).build();
}
private FilterChain getFilters() {
SNIFilter sniFilter = getSniFilter();
final FilterChain chain = FilterChainBuilder.stateless()
.add(new TransportFilter())
.add(sniFilter)
.add(new StringFilter())
.add(new BaseFilter() {
@Override
public NextAction handleRead(final FilterChainContext ctx)
throws IOException {
return ctx.getInvokeAction();
}
})
.build();
return chain;
}
private SNIFilter getSniFilter() {
final Attribute<String> sniHostAttr = Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("sni-host-attr");
SNIFilter sniFilter = new SNIFilter();
sniFilter.setServerSSLConfigResolver(new SNIServerConfigResolver() {
@Override
public SNIConfig resolve(Connection connection, String hostname) {
sniHostAttr.set(connection, hostname);
if (StringUtils.isEmpty(hostname)) {
throw new IllegalArgumentException("SNI Has not been sent");
}
return SNIConfig.newServerConfig(sslServerEngineConfig);
}
});
return sniFilter;
}
private SSLContextConfigurator createSSLContextConfigurator() {
SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();
ClassLoader cl = HttpRequestSNITestCase.class.getClassLoader();
URL cacertsUrl = cl.getResource("trustStore");
if (cacertsUrl != null) {
sslContextConfigurator.setTrustStoreFile(cacertsUrl.getFile());
sslContextConfigurator.setTrustStorePass("myPassword");
}
URL keystoreUrl = cl.getResource("serverKeystore");
if (cacertsUrl != null) {
sslContextConfigurator.setKeyStoreFile(keystoreUrl.getFile());
sslContextConfigurator.setKeyStorePass("myPassword");
sslContextConfigurator.setKeyPass("myPassword");
}
return sslContextConfigurator;
}
public class Server {
private HttpServer webServer;
protected void startServer() throws IOException {
SSLEngineConfigurator sslServerEngineConfig = new SSLEngineConfigurator(createSSLContextConfigurator().createSSLContext(), false, false, false);
NetworkListener networkListener = new NetworkListener("sample-listener", "localhost", httpsPort.getNumber());
networkListener.setTransport(createMockServerTransport());
networkListener.setSSLEngineConfig(sslServerEngineConfig);
webServer = HttpServer.createSimpleServer();
webServer.addListener(networkListener);
networkListener.setSecure(true);
networkListener.getTransport().setProcessor(getFilters());
FilterChain chain = networkListener.getFilterChain();
webServer.start();
}
protected void stopServer() {
webServer.shutdownNow();
}
}
为了更新 HttpServer 过滤器链,您必须使用 AddOn:
protected void startServer() throws IOException {
NetworkListener networkListener = new NetworkListener("sample-listener", "localhost", 8081);
sslServerEngineConfig = new SSLEngineConfigurator(createSSLContextConfigurator().createSSLContext(), false, false, false);
networkListener.setSSLEngineConfig(sslServerEngineConfig);
networkListener.setSecure(true);
networkListener.registerAddOn(new SniAddOn());
webServer = HttpServer.createSimpleServer();
webServer.addListener(networkListener);
webServer.start();
}
private class SniAddOn implements AddOn {
public void setup(NetworkListener networkListener,
FilterChainBuilder builder) {
// replace SSLFilter (if any) with SNIFilter
final int idx = builder.indexOfType(SSLBaseFilter.class);
if (idx != -1) {
builder.set(idx, getSniFilter());
}
}
}