无法使用 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());
        }
    }
}