Apache HttpClient 4.3和x509客户端证书进行身份验证

问题描述 投票:4回答:3

现在我正在寻找有关如何通过HttpComponentsMessageSender(不相关)重写客户端x509证书身份验证的弃用解决方案的任务的解决方案。

例如,弃用的解决方案是:

    SSLSocketFactory lSchemeSocketFactory = new SSLSocketFactory(this.keyStore, this.keyStorePassword);
    Scheme sch = new Scheme("https", 443, lSchemeSocketFactory);

    DefaultHttpClient httpClient = (DefaultHttpClient)getHttpClient();
    httpClient.getConnectionManager().getSchemeRegistry().register(sch);

作为我使用的CloseableHttpClient的新解决方案:

    SSLContextBuilder sslContextBuilder = SSLContexts.custom()
            // this key store must contain the key/cert of the client
            .loadKeyMaterial(keyStore, keyStorePassword.toCharArray());

    if (trustStore != null) {
        // this key store must contain the certs needed and trusted to verify the servers cert
        sslContextBuilder.loadTrustMaterial(trustStore);
    }

    SSLContext sslContext = sslContextBuilder.build();

    LayeredConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);

    // Create a registry of custom connection socket factories for supported
    // protocol schemes / https
    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("https", sslsf)
            .register("http", new PlainConnectionSocketFactory())
            .build();

    PoolingHttpClientConnectionManager connPoolControl =
            new PoolingHttpClientConnectionManager(socketFactoryRegistry);
    setConnPoolControl(connPoolControl);
    getClientBuilder().setSSLSocketFactory(sslsf);

我仍然从服务器上禁止403。但是当我使用“弃用”版本的解决方案时,它的效果很好。 SSL证书已签署Thawte。

任何的想法?谢谢

java ssl httpclient x509certificate spring-ws
3个回答
5
投票

Tomas,也许为时已晚,但我希望它会帮助其他人......有一种方法,我用它来创建使用Apache HttpClient 4.3的CloseableHttpClient:

public static CloseableHttpClient prepareClient() {
    try {           
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).useTLS().build();
        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        builder.setSSLSocketFactory(sslConnectionFactory);
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", sslConnectionFactory)
                .register("http", new PlainConnectionSocketFactory())
                .build();
        HttpClientConnectionManager ccm = new BasicHttpClientConnectionManager(registry);
        builder.setConnectionManager(ccm);
        return builder.build();
    } catch (Exception ex) {

        return null;
    }
}

Apache Foundation将org.apache.http.conn.ssl.SSLContextBuilder,org.apache.http.conn.ssl.SSLContexts和org.apache.http.conn.ssl.SSLSocketFactory从4.4版开始弃用,There你可以找到Apache客户端4.5.2 API已删除列表。因此,可以像这样改变以前的方法:

public static CloseableHttpClient prepareClient() {
    try {
        SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
        HttpClientBuilder builder = HttpClientBuilder.create();
        SSLConnectionSocketFactory sslConnectionFactory = 
                new SSLConnectionSocketFactory(sslContext.getSocketFactory(), 
                        new NoopHostnameVerifier());
        builder.setSSLSocketFactory(sslConnectionFactory);
        Registry<ConnectionSocketFactory> registry = 
                RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", sslConnectionFactory)
                .register("http", new PlainConnectionSocketFactory())
                .build();
        HttpClientConnectionManager ccm = new BasicHttpClientConnectionManager(registry);
        builder.setConnectionManager(ccm);
        return builder.build();
    } catch (Exception ex) {
        LOG.error("couldn't create httpClient!! {}", ex.getMessage(), ex);
        return null;
    }
}

NoopHostnameVerifier

NO_OP HostnameVerifier实际上关闭了主机名验证。这个实现是一个无操作,并且永远不会抛出SSLException。

如果需要验证主机名,可以使用DefaultHostnameVerifier,也可以实现自定义主机名验证程序。


1
投票

您需要创建一个包含可信CA的密钥库,即qazxsw poi。在此密钥库中,您应该只放置应用程序要连接的服务器的证书。

然后,您需要一个用于服务器身份的密钥库,即trust.jks。在此密钥库中,您应该将私钥+证书+ CA链存放在应用程序将用于向服务器验证自身的别名(名称)下。

然后你可以像这样建立identity.jks

HttpClient

要构建public static HttpClient getHttpClient() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException, KeyManagementException { KeyStore identityKeyStore = KeyStore.getInstance("jks"); identityKeyStore.load(MyClass.class.getClassLoader().getResourceAsStream("identity.jks"), "identity_password".toCharArray()); KeyStore trustKeyStore = KeyStore.getInstance("jks"); trustKeyStore.load(MyClass.class.getClassLoader().getResourceAsStream("trust.jks"), "trust_password".toCharArray()); SSLContext sslContext = SSLContexts .custom() // load identity keystore .loadKeyMaterial(identityKeyStore, "identity_password".toCharArray(), new PrivateKeyStrategy() { @Override public String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket) { return "identity_alias"; } }) // load trust keystore .loadTrustMaterial(trustKeyStore, null) .build(); SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1.2", "TLSv1.1"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); return HttpClients.custom() .setSSLSocketFactory(sslConnectionSocketFactory) .build(); } ,您需要CA链,公钥和私钥:

identity.jks

对于$1 = mycustomidentity # make the keycert bundle for pkcs12 keystore cat intermediate/certs/ca-chain.cert.pem \ intermediate/certs/$1.cert.pem \ intermediate/private/$1.key.pem \ > intermediate/keycerts/$1.full-chain.keycert.pem # generate the pkcs12 keystore with the alias of the server url openssl pkcs12 -export \ -in intermediate/keycerts/$1.full-chain.keycert.pem \ -out intermediate/pkcs12s/$1.full-chain.p12 \ -name $1 \ -noiter -nomaciter # .p12 to .jks keytool -importkeystore -srckeystore $1.full-chain.p12 \ -srcstoretype pkcs12 -srcalias $1 \ -destkeystore identity.jks -deststoretype jks \ -deststorepass identity_password -destalias identity_alias 文件,您只需要服务器的证书(请参阅trust.jkshttps://stackoverflow.com/a/36427118/2692914),更改别名没有问题:

https://stackoverflow.com/a/7886248/2692914

0
投票

下面是HttpClient 4.4+的代码(更新的@Daniyar代码为4.4+)

# .crt, .cer into a .jks
keytool -import -alias trust_alias -file server_certificate.crt \
    -keystore trust.jks
© www.soinside.com 2019 - 2024. All rights reserved.