2015-09-15 9 views
18

は、私が強制したいはApache CommonsのHTTPクライアントHTTPS用のみプロトコルとしてTLS 1.2を使用する(バージョン3.1)。Commons HTTPClient 3.1にHTTPS専用のTLS 1.2を使用させるにはどうすればいいですか?

これは、サーバーがTLS 1.2にアップグレードされ、以前のプロトコルを受け入れなくなったため(「接続リセット」が返されるためです)。

HTTP-ClientはAxis2とともにSOAPを作成するために使用されます。 HttpClientの設定に使用されるコードの一部は次のとおりです。

MultiThreadedHttpConnectionManager connMgr = new MultiThreadedHttpConnectionManager(); 
this.httpClient = new HttpClient(connMgr); 

// initialize HttpClient parameters 
HttpClientParams hcParams = this.httpClient.getParams(); 

// Maximum time to wait to receive connection from pool 
hcParams.setConnectionManagerTimeout(this.maxWait); 
hcParams.setSoTimeout(this.timeout); 
hcParams.setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(this.retryCount, false)); 

// Initialize global Connection manager parameters 
HttpConnectionManagerParams cmParams = connMgr.getParams(); 
cmParams.setDefaultMaxConnectionsPerHost(this.maxActive); 
cmParams.setStaleCheckingEnabled(this.checkStaleConnections); 
cmParams.setConnectionTimeout(this.timeout); 

ありがとうございました!

+0

私はあなたがあまりにも古いバージョンのJavaを使用していることを前提としています。あなたのJavaがJava 1.2をまったく使用できると確信していますか? –

+0

いいえJava 7を使用していますが、コードは古すぎず、今まではうまくいきます。 –

答えて

20

あまりにも悪い回答はありませんでした。

String scheme = "https"; 
Protocol baseHttps = Protocol.getProtocol(scheme); 
int defaultPort = baseHttps.getDefaultPort(); 

ProtocolSocketFactory baseFactory = baseHttps.getSocketFactory(); 
ProtocolSocketFactory customFactory = new CustomHttpsSocketFactory(baseFactory); 

Protocol customHttps = new Protocol(scheme, customFactory, defaultPort); 
Protocol.registerProtocol(scheme, customHttps); 

サンプルのカスタムソケットファクトリコードはhereを発見されたが、代わりに私がやった:私が最初にあなたがあなたが、CustomHttpSocketFactory書き、それを行うことができました

public class CustomHttpsSocketFactory implements SecureProtocolSocketFactory 
{ 

    private final SecureProtocolSocketFactory base; 

    public CustomHttpsSocketFactory(ProtocolSocketFactory base) 
    { 
     if(base == null || !(base instanceof SecureProtocolSocketFactory)) throw new IllegalArgumentException(); 
     this.base = (SecureProtocolSocketFactory) base; 
    } 

    private Socket acceptOnlyTLS12(Socket socket) 
    { 
     if(!(socket instanceof SSLSocket)) return socket; 
     SSLSocket sslSocket = (SSLSocket) socket; 
     sslSocket.setEnabledProtocols(new String[]{"TLSv1.2" }); 
     return sslSocket; 
    } 

    @Override 
    public Socket createSocket(String host, int port) throws IOException 
    { 
     return acceptOnlyTLS12(base.createSocket(host, port)); 
    } 
    @Override 
    public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException 
    { 
     return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort)); 
    } 
    @Override 
    public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException 
    { 
     return acceptOnlyTLS12(base.createSocket(host, port, localAddress, localPort, params)); 
    } 
    @Override 
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException 
    { 
     return acceptOnlyTLS12(base.createSocket(socket, host, port, autoClose)); 
    } 

} 
+0

'SecureProtocolSocketFactory'は' SSLSocketFactory'と異なっていますか? –

+1

SecureProtocolSocketFactoryは、カスタムソケットファクトリの実装に役立つApache HTTPClientのインターフェイスです。私は** javaのSSLSocketFactoryはこの場合にはあまり役に立たないと信じています。 –

+0

@ united-expression HTTPクライアント(バージョン4.1)を使用していることを除いて、同じ要件があります。この登録されたプロトコルでhttpClientをどこにバインドしているのかはっきりしていませんが、あなたのコードは役に立ちますか? – LoveForDroid

2

コード内にSocket参照が必要です。あなたは交換していない限り、あなたがJRE8を(使用している場合

を:それはあなたがあなたのクライアントを書いているし、どのようなJREのバージョンを使用しているかに依存

if (socket != null && (socket instanceof SSLSocket)) { 
    ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"}); 
} 
1

:次に、あなたがこのようにそれに有効なプロトコルを設定することができますJRE8に付属しているデフォルトのSunJSSE)には、システムプロパティ "jdk.tls.client.protocols"があります。デフォルトでは、ここで言及しているものは、すべてのクライアント通信に使用されます。

クライアント接続にHttpsURLConnectionオブジェクトを使用している場合は、システムプロパティ "https.protocols"を使用できます。これは、JRE8だけでなく、すべてのJREバージョンで機能します。

TLSクライアントの場合、JRE8で何も指定しないと、TLSv1、v1.1およびv1.2が有効になるため、このバージョンのいずれかをサポートするサーバーで動作します。しかし、JRE7ではデフォルトでTLSv1だけが有効になっています。

あなたのコードでは、いつでもデフォルトを無視したり、システムプロパティを渡すことができます。コードで設定したものが優先されます。あなたは生のソケットとSSLEngineのを使用している場合がある場合)...コードで

1を上書きするには、uがSSLEngineの(sslEngine.setEnabledProtocols(..)

2)でプロトコルと暗号を設定することができます(sslSocket.setEnabledProtocols(..)

必要なプロトコルを有効にしてSSLContextを取得し、それを使用するSSLコンポーネントを使用することもできます。SSLContext.getInstance(SSLSocketを使用して、 "TLSvx.x")。デフォルトでは、TLSvx.xが有効になっているすべてのプロトコルでコンテキストが返されますので、 "jdk.tls.client.protocols"を設定していれば、これらのプロトコルを有効にしたコンテキストが返されます。

それは、コード内のハードコードされたプロトコルには良い考えではないでしょう。 TLSの一部のバージョンで古いサーバーや重大な脆弱性が発生するため、特定のバージョンのクライアントに遭遇することがよくあります。システムのプロパティを使って設定するか、sslsocketまたはsslengineを明示的に設定している場合でも、それをいくつかのconfファイルから読み込みます。

も参照してください:あなたはこの古いとメンテナンスされていないソフトウェアを使用しているので

https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html

http://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html

関連する問題