HTTP Apache,ssl 身份验证在 Java 1.8 中不起作用

HTTP Apache, ssl authentication does not work in Java 1.8

以下代码在 Java(运行时)1.6 中运行良好。和 1.7,但它会产生:1.8 中的 peer not authenticated exception。它是在 Java 1.6.

中编译的

它使用apache的httpcore (v4.0.1) 和httpclient (v4.0)。任何线索为什么会这样?或者我应该将它重写为 httpclient 4.5?谁能举个例子?

private InputStream getStreamFromHttps(String url) throws HttpException {
        HttpParams httpParams = new BasicHttpParams();

        HttpConnectionParams.setConnectionTimeout(httpParams, 30000);
        HttpConnectionParams.setSoTimeout(httpParams, 15000);

        DefaultHttpClient httpclient = new DefaultHttpClient(httpParams);

        try {

            KeyStore trustStore = KeyStore.getInstance(KeyStore
                    .getDefaultType());
            InputStream instream = trustKeyLocation.getInputStream();


            try {
                trustStore.load(instream, trustKeyFilePassword.toCharArray());
            } finally {
                instream.close();
            }

            SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
            Scheme sch = new Scheme("https", socketFactory, 443);
            httpclient.getConnectionManager().getSchemeRegistry().register(sch);
            HttpGet httpget = new HttpGet(url);

            HttpResponse response = httpclient.execute(httpget);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                return null;
            }

            BufferedInputStream responseStream = new BufferedInputStream(
                    response.getEntity().getContent());

            return responseStream;
        } catch (Exception ex) {
            throw new HttpException("Https acces failed", ex);
        }
    }

@Warren - 感谢您链接相关问题,我今天将尝试解决它。这是堆栈跟踪。我之前没有发布它,因为它看起来像证书有问题。所以这可能会误导 IMO。

Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:431) ~[na:na]
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:339) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:123) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576) ~[httpclient-4.0.jar:4.0]
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554) ~[httpclient-4.0.jar:4.0]

@Warren - 我已经将 SSLSocketFactory 和 .setEnbaledProtocols(...) 子类化为链接问题,但现在可用。

然后我启用了"javax.net.debug"、"ssl:handshake:verbose"并得到了

Java1.7

10:35:57.995 [main] DEBUG o.a.h.impl.client.ClientParamsStack - 'http.connection.timeout': 30000
10:35:57.995 [main] DEBUG o.a.h.impl.client.ClientParamsStack - 'http.socket.timeout': 15000
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(15000) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1443515758 bytes = { 189, 94, 204, 7, 214, 235, 42, 74, 179, 234, 136, 224, 40, 90, 63, 198, 138, 212, 83, 2, 140, 99, 151, 102, 220, 2, 54, 129 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
***
main, WRITE: TLSv1 Handshake, length = 149
main, READ: TLSv1 Handshake, length = 1583
*** ServerHello, TLSv1
RandomCookie:  GMT: -567721376 bytes = { 134, 214, 213, 200, 86, 83, 10, 155, 219, 85, 187, 15, 221, 196, 224, 101, 228, 139, 220, 255, 63, 254, 39, 179, 226, 24, 50, 189 }
Session ID:  {}
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Initialized:  [Session-1, SSL_RSA_WITH_RC4_128_MD5]
** SSL_RSA_WITH_RC4_128_MD5
*** Certificate chain

Java1.8

10:34:39.056 [main] DEBUG o.a.h.impl.client.ClientParamsStack - 'http.connection.timeout': 30000
10:34:39.056 [main] DEBUG o.a.h.impl.client.ClientParamsStack - 'http.socket.timeout': 15000
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(15000) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1443515679 bytes = { 0, 208, 71, 217, 206, 77, 79, 188, 232, 167, 31, 200, 170, 23, 75, 73, 232, 211, 86, 236, 96, 4, 73, 82, 173, 88, 241, 128 }
Session ID:  {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
***
main, WRITE: TLSv1 Handshake, length = 151
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1.2 ALERT:  fatal, handshake_failure
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
main, IOException in getSession():  javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
main, called close()
main, called closeInternal(true)
10:34:39.203 [main] DEBUG o.a.h.i.conn.DefaultClientConnection - Connection shut down
main, called close()
main, called closeInternal(true)
10:34:39.203 [main] DEBUG o.a.h.i.conn.SingleClientConnManager - Releasing connection org.apache.http.impl.conn.SingleClientConnManager$ConnAdapter@a3ec6b

看来我有答案了。我不必强制执行 TLSv1,但我必须添加 JDK1.8 中不支持的密码之一,即:

SSL_RSA_WITH_RC4_128_SHASSL_RSA_WITH_RC4_128_MD5.

这是代码。 class 实现这些方法扩展了 SSLSocketFactory

@Override 
public Socket createSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException, UnknownHostException { 
    SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    sslSocket.setEnabledCipherSuites(newCiphers);
    return sslSocket;

} 

@Override 
public Socket createSocket() throws IOException { 
    SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket();
    sslSocket.setEnabledCipherSuites(newCiphers);
    return sslSocket;
} 

newCiphers var 是密码的 String[]。