Apache HTTP客户端 – 如何加载多个密钥库?

huangapple 未分类评论65阅读模式
英文:

Apache HTTP client - How to load multiple key-stores?

问题

在我的Java项目中,我正在使用Apache HTTP客户端。

我能够加载单个路由的SSL密钥库和信任库。

以下是我正在使用的代码片段:

protected void initConnectionManager(HttpClientProps props) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException, CertificateException, IOException {
    PoolingHttpClientConnectionManager connectionManager = createConnectionManager(buildRegistry(props));
    connectionManager.setMaxTotal(props.getMaxThreadPool());
    connectionManager.setDefaultMaxPerRoute(props.getDefaultMaxPerRoute());
    setConnManager(connectionManager);
}

protected Registry<ConnectionSocketFactory> buildRegistry(HttpClientProps props) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
    final RegistryBuilder<ConnectionSocketFactory> registryBuilder;
    if (props.isSslEnabled()) {
        final KeyStore ts = getKeyStoreInstance(), ks = getKeyStoreInstance();
        ts.load(new FileInputStream(props.getTrustStorePath()), props.getTrustStoreKey().toCharArray());
        ks.load(new FileInputStream(props.getKeyStorePath()), props.getKeyStoreKey().toCharArray());
        final SSLContext ssl = buildSslContext(props, ts, ks);
        final ConnectionSocketFactory sslConnectionFactory = getSslConnectionFactory(ssl);
        registryBuilder = createRegistryBuilder(HTTPS, sslConnectionFactory);
    } else {
        registryBuilder = createRegistryBuilder(HTTP, new PlainConnectionSocketFactory());
    }
    return registryBuilder.build();
}

protected RegistryBuilder<ConnectionSocketFactory> createRegistryBuilder(String id, ConnectionSocketFactory factory) {
    return RegistryBuilder.<ConnectionSocketFactory>create().register(id, factory);
}

protected SSLContext buildSslContext(HttpClientProps props, KeyStore ts, KeyStore ks) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    return SSLContexts.custom()
            .loadTrustMaterial(ts, this::getTrustStrategy)
            .loadKeyMaterial(ks, props.getKeyStoreKey().toCharArray())
            .setSecureRandom(new SecureRandom())
            .build();
}

现在,我正试图弄清楚如何处理多个路由,例如:

  1. https://route1.com/path
  2. https://route2.com/path

如果这两个路由需要不同的密钥库(JKS)和信任库(JKS),那么如何在同一个客户端中设置它,并配置它以在route1使用keystore1和truststore1,在route2使用keystore2和truststore2?

或者,我应该为每个路由使用一个新的httpclient对象,并分别设置keystore和truststore?[在这种方法中,将为每个客户端创建一个新的线程池。我正在尝试避免这种情况。]

英文:

I am using Apache http client in my Java project.

I am able to load the ssl keystore and truststore for a single route.

Here's the code snippet I am using:

protected void initConnectionManager(HttpClientProps props) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException, CertificateException, IOException {
    PoolingHttpClientConnectionManager connectionManager = createConnectionManager(buildRegistry(props));
    connectionManager.setMaxTotal(props.getMaxThreadPool());
    connectionManager.setDefaultMaxPerRoute(props.getDefaultMaxPerRoute());
    setConnManager(connectionManager);
}

protected Registry&lt;ConnectionSocketFactory&gt; buildRegistry(HttpClientProps props) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
    final RegistryBuilder&lt;ConnectionSocketFactory&gt; registryBuilder;
    if (props.isSslEnabled()) {
        final KeyStore ts = getKeyStoreInstance(), ks = getKeyStoreInstance();
        ts.load(new FileInputStream(props.getTrustStorePath()), props.getTrustStoreKey().toCharArray());
        ks.load(new FileInputStream(props.getKeyStorePath()), props.getKeyStoreKey().toCharArray());
        final SSLContext ssl = buildSslContext(props, ts, ks);
        final ConnectionSocketFactory sslConnectionFactory = getSslConnectionFactory(ssl);
        registryBuilder = createRegistryBuilder(HTTPS, sslConnectionFactory);
    } else {
        registryBuilder = createRegistryBuilder(HTTP, new PlainConnectionSocketFactory());
    }
    return registryBuilder.build();
}

protected RegistryBuilder&lt;ConnectionSocketFactory&gt; createRegistryBuilder(String id, ConnectionSocketFactory factory) {
    return RegistryBuilder.&lt;ConnectionSocketFactory&gt;create().register(id, factory);
}

protected SSLContext buildSslContext(HttpClientProps props, KeyStore ts, KeyStore ks) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    return SSLContexts.custom()
            .loadTrustMaterial(ts, this::getTrustStrategy)
            .loadKeyMaterial(ks, props.getKeyStoreKey().toCharArray())
            .setSecureRandom(new SecureRandom())
            .build();
}

Now I am trying to figure out for multiple routes for example:

  1. https://route1.com/path
  2. https://route2.com/path

If both the routes need different keystore JKS and truststore JKS
then how do I set that in the same client and configure it to use keystore1 and truststore1 for route1 and keystore2 and truststore2 for route2?

Or should I use a new object of the httpclient for each route and set the keystore and truststore respectively? [In this approach the catch is a new thread pool will be created for each client. I am trying to avoid it.]

huangapple
  • 本文由 发表于 2020年7月27日 21:54:53
  • 转载请务必保留本文链接:https://java.coder-hub.com/63116869.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定