web-dev-qa-db-ja.com

Commons HTTPClient 3.1にHTTPSのみにTLS 1.2を使用させるにはどうすればよいですか?

Apache Commons HTTP-Client(version .1)を強制的に使用したいTLS 1.2only HTTPSのプロトコル.

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

おそらく関係のないさらなるコンテキストについては、HTTPクライアントを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);

助けてくれてありがとう!

21

誰も答えなかったのは残念です。私はそれを行うことができました、最初にCustomHttpSocketFactoryを書いてから、次のようにします:

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 が、代わりに私は:

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));
   }

}
25

コードにはSocket参照が必要です。次に、有効なプロトコルを次のように設定できます。

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

クライアントの作成方法と使用しているJREバージョンによって異なります。

JRE8を使用している場合(JRE8に付属するデフォルトのSunJSSEを置き換えていない場合)、システムプロパティ「jdk.tls.client.protocols」があります。デフォルトでは、ここで言及するものはすべてのクライアント通信に使用されます。

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

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

コードでは、uは常にデフォルトまたはシステムプロパティを通過するものをオーバーライドできます。コードで設定したものが優先されます。コードでオーバーライドするには...

1)rawソケットとSSLEngineを使用している場合、uはSSLEngineでプロトコルと暗号を設定できます(sslEngine.setEnabledProtocols(..)

2)SSLSocketを使用している場合、uはSSLSocketでプロトコルと暗号を設定できます(sslSocket.setEnabledProtocols(..)

また、必要なプロトコルを有効にしてSSLContextを取得し、使用するSSLコンポーネントにそれを使用することもできます。 SSLContext.getInstance( "TLSvx.x")。デフォルトでは、TLSvx.xが有効になっているよりも小さいすべてのプロトコルを含むコンテキストを返すことに注意してください。 uが「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

2
Rajesh